asp.net file upload function of single file multiple files custom thumbnail generation watermark

  • 2020-05-12 02:30:02
  • OfStack

preface
Upload function, is often used by everyone, maybe every project can be used. There are upload codes all over the Internet. A lot better than what I wrote. I'm just sharing my code here.
Function realization point
1. Upload a single file;
2. Multiple file uploads;
3. For pictures and other types of images, the size of thumbnail can be customized;
4. File server expansion.
model
The main design pattern used is the "template method".
The advantages and disadvantages of this article
1. You can customize the size of the thumbnail image. Like the small life sports outdoor mall (http: / / sports. 8 t8x. com /), taobao and other sites, a lot of goods they need to upload pictures, very useful.
2. Disadvantages: I am not familiar with the namespace System.Drawing, and the method of generating images is copied from the Internet. I think the methods of generating images obtained by myself are not very good.
Code implementation
1. Interface definition
 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Web; 
namespace CCNF.Plugin.Upload 
{ 
/// <summary> 
///  Upload function interface  
/// </summary> 
/// <creator>Marc</creator> 
public interface IUpload 
{ 
/// <summary> 
///  Upload a single file.  
/// </summary> 
/// <param name="sourcefile"></param> 
/// <returns></returns> 
/// <author>Marc</author> 
int SaveAs(HttpPostedFile sourcefile); 
} 
} 

2. Abstract template method class
Because of the code insertion approach, cnblogs reported an error, so I had to use the original copy approach, which might have seemed uncomfortable.
 
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Configuration; 
using System.IO; 
using System.Net; 
using System.Data; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Drawing.Drawing2D; 
using System.Web; 
using System.Collections; 
namespace CCNF.Plugin.Upload 
{ 
/// <summary> 
///  Upload function.  
///  This class is available for upload 1 General method.  
/// </summary> 
/// <creator>Marc</creator> 
public abstract class UploadAbstract : IUpload 
{ 
#region  Constant properties  
/// <summary> 
///  File extensions that allow uploading.  
///  Multiple file extensions are separated by English commas.  
///  The default from the Web.config In the acquisition.  
/// </summary> 
private readonly string UPLOADEXTENTION = ConfigurationManager.AppSettings["UploadExtention"]; 
private string uploadExtention = null; 
/// <summary> 
///  File extensions that allow uploading.  
///  Multiple file extensions are separated by English commas.  
///  The default from the Web.config In the acquisition.  
/// </summary> 
public string UploadExtention 
{ 
get 
{ 
if (string.IsNullOrEmpty(this.uploadExtention)) 
{ 
if (string.IsNullOrEmpty(UPLOADEXTENTION)) 
{ 
throw new Exception("web.config Not in the configuration UploadExtention attribute "); 
} 
this.uploadExtention = UPLOADEXTENTION; 
} 
return this.uploadExtention; 
} 
set 
{ 
this.uploadExtention = value; 
} 
} 
/// <summary> 
///  Maximum size of a single file allowed for upload.  
///  The unit is k .  
///  The default from the Web.config In the acquisition.  
/// </summary> 
private readonly int UPLOADLENGTH = Convert.ToInt16(ConfigurationManager.AppSettings["UploadLength"]); 
private int uploadLength = 0; 
/// <summary> 
///  Maximum size of a single file allowed for upload.  
///  The unit is.  
///  The default from the Web.config In the acquisition.  
/// </summary> 
public int UploadLength 
{ 
get 
{ 
if (this.uploadLength == 0) 
{ 
this.uploadLength = UPLOADLENGTH; 
} 
return this.uploadLength; 
} 
set 
{ 
this.uploadLength = value; 
} 
} 
/// <summary> 
///  Which physical disk should the uploaded files be saved to?  
///  This value is the strict physical folder path. Such as: E:\CCNF\ 
///  Note: there must be disk characters.  
///  This belongs to the extended image server data store.  
///  The default from the Web.config In the acquisition.  
/// </summary> 
private readonly string UPLOADPHYSICALPATH = ConfigurationManager.AppSettings["UploadPhysicalPath"]; 
private string uploadPhysicalPath = null; 
/// <summary> 
///  Which physical disk should the uploaded files be saved to?  
///  This value is the strict physical folder path. Such as: E:\CCNF\ 
///  Note: there must be disk characters.  
///  This property is used to extend the image server data store.  
///  The default from the Web.config In the acquisition.  
/// </summary> 
public string UploadPhysicalPath 
{ 
get 
{ 
if (string.IsNullOrEmpty(this.uploadPhysicalPath)) 
{ 
if (string.IsNullOrEmpty(UPLOADPHYSICALPATH)) 
{ 
throw new Exception("web.config Not in the configuration UploadPhysicalPath attribute "); 
} 
this.uploadPhysicalPath = UPLOADPHYSICALPATH; 
} 
return this.uploadPhysicalPath; 
} 
set 
{ 
this.uploadPhysicalPath = value; 
} 
} 
#endregion 
#region  The enumeration  
/// <summary> 
///  Watermark type  
/// </summary> 
public enum WatermarkTypeEnum 
{ 
/// <summary> 
///  Text watermarking  
/// </summary> 
String = 1, 
/// <summary> 
///  Image watermarking  
/// </summary> 
Image = 2 
} 
/// <summary> 
///  Upload the result  
/// </summary> 
protected enum UploadResultEnum 
{ 
/// <summary> 
///  No object to upload was specified  
/// </summary> 
UploadedObjectIsNull = -9, 
/// <summary> 
///  File extensions are not allowed  
/// </summary> 
ExtentionIsNotAllowed = -2, 
/// <summary> 
///  The file size is not limited  
/// </summary> 
ContentLengthNotWithinTheScope = -1, 
/// <summary> 
///  The physical save path for the file is not configured or specified  
/// </summary> 
UploadPhysicalPathNoSpecify = -20, 
/// <summary> 
///  The relative file physical path for the image watermark is not specified  
/// </summary> 
ImageWartermarkPathNoSpecify = -30, 
/// <summary> 
///  Text without watermark specified  
/// </summary> 
StringWatermarkNoSpecify = -31, 
/// <summary> 
///  Failed to upload original file  
/// </summary> 
UploadOriginalFileFailure = 0, 
/// <summary> 
///  Failed to generate thumbnail  
/// </summary> 
CreateThumbnailImageFailure = -3, 
/// <summary> 
///  An unknown error  
/// </summary> 
UnknownError = -4, 
/// <summary> 
///  Uploaded successfully  
/// </summary> 
Success = 1 
} 
#endregion 
#region  Upload properties  
/// <summary> 
///  Save the folder.  
///  The format is as follows:  upload\  or  images\  or  upload\user\  And so on. In order to \ At the end.  
///  Disk characters are not allowed  
/// </summary> 
public string SaveFolder { get; set; } 
/// <summary> 
///  Custom generation of new folders.  
///  The format is as follows:  upload\  or  images\  or  upload\2011\10\8\  And so on. In order to \ At the end.  
///  Final folder  = UploadPhysicalPath + SaveFolder + Folder 
/// </summary> 
public string Folder { get; set; } 
/// <summary> 
///  Whether to generate watermark.  
///  Watermark generation is not enabled by default.  
/// </summary> 
public bool IsMakeWatermark { get; set; } 
private int watermarkType = (int)WatermarkTypeEnum.String; 
/// <summary> 
///  How to generate watermark: string From the text, image Generated from the image.  
///  The default is a text watermark  
/// </summary> 
public int WatermarkType 
{ 
get 
{ 
return this.watermarkType; 
} 
set 
{ 
this.watermarkType = value; 
} 
} 
/// <summary> 
///  Watermark text.  
/// </summary> 
public string Watermark { get; set; } 
/// <summary> 
///  The location of the watermark image.  
///  Provides the relative location of the image watermark.  
///  No disk character is included.  
/// </summary> 
public string ImageWartermarkPath { get; set; } 
/// <summary> 
///  The new file path generated after uploading.  
///  This path is a relative physical path and does not contain a disk character.  
/// </summary> 
public string NewFilePath { get; protected set; } 
/// <summary> 
///  Generate the length and width of the thumbnail image,   is 1 a 2 Dimensional data.  
///  Such as: int a[3,2]={{1,2},{5,6},{9,10}} .  
///  If the uploaded file is an image type and you want to generate a thumbnail of the image, save the required dimensions as an array here.  
/// </summary> 
public int[,] PicSize { get; set; } 
/// <summary> 
///  Generate image address, with 2 Dimensional array PicSize The length of theta is corresponding.  
///  If there is an incoming PicSize Array, then the system will return after the upload PicPath The array.  
///  This array is its final upload path for the user to perform database operations on this value.  
///  Produced by the PicPath The index location and PicSize is 11 The corresponding.  
///  This property has been declared read-only.  
/// </summary> 
public string[] PicPath { get; protected set; } 
#endregion 
/// <summary> 
///  Upload a single file  
/// </summary> 
/// <param name="sourcefile"></param> 
/// <param name="upload"></param> 
/// <returns></returns> 
/// <author>Marc</author> 
public virtual int SaveAs(HttpPostedFile sourcefile) 
{ 
int result = 0; 
// An unknown error  
UploadResultEnum uploadResultEnum = UploadResultEnum.UnknownError; 
if (sourcefile == null) 
{ 
// No object to upload was specified  
uploadResultEnum = UploadResultEnum.UploadedObjectIsNull; 
} 
else 
{ 
uploadResultEnum = Upload(sourcefile); 
} 
result = (int)uploadResultEnum; 
return result; 
} 
/// <summary> 
///  Upload a file  
/// </summary> 
/// <param name="sourcefile"></param> 
/// <returns></returns> 
/// <author>Marc</author> 
private UploadResultEnum Upload(HttpPostedFile sourcefile) 
{ 
#region  Detection before uploading  
if (string.IsNullOrEmpty(UploadPhysicalPath)) 
{ 
// The physical save path for the file is not configured or specified  
return UploadResultEnum.UploadPhysicalPathNoSpecify; 
} 
string fileName = sourcefile.FileName; 
string fileExtention = Path.GetExtension(fileName); 
if (!CheckExtention(fileExtention)) 
{ 
// File extensions are not allowed  
return UploadResultEnum.ExtentionIsNotAllowed; 
} 
int fileLength = sourcefile.ContentLength; 
if (fileLength <= 0 || fileLength > UploadLength * 1024) 
{ 
// The file size is not limited  
return UploadResultEnum.ContentLengthNotWithinTheScope; 
} 
// Create a folder to save  
string physicalPath = UploadPhysicalPath + SaveFolder + Folder; 
if (!Directory.Exists(physicalPath)) 
{ 
Directory.CreateDirectory(physicalPath); 
} 
#endregion 
string newFileName = "Ori_" + Guid.NewGuid().ToString() + fileExtention; 
// The relative physical path of the new file  
string newFilePath = physicalPath + newFileName; 
#region  Save the original file  
if (!IsMakeWatermark) // When watermarking is not enabled  
{ 
// Save the file  
sourcefile.SaveAs(newFilePath); 
} 
else // Request to generate watermark  
{ 
Image bitmap = new System.Drawing.Bitmap(sourcefile.InputStream); 
Graphics g = Graphics.FromImage(bitmap); 
g.InterpolationMode = InterpolationMode.High; 
g.SmoothingMode = SmoothingMode.AntiAlias; 
Image fromImg = null; 
try 
{ 
// Clear the entire drawing surface and fill with a transparent background color  
//g.Clear(Color.Transparent); 
if (WatermarkType == (int)WatermarkTypeEnum.String) // Generate text watermark  
{ 
if (string.IsNullOrEmpty(Watermark)) 
{ 
// Text without watermark specified  
return UploadResultEnum.StringWatermarkNoSpecify; 
} 
Color color = Color.FromArgb(120, 255, 255, 255); 
Brush brush = new SolidBrush(color); 
//  The font size is automatically scaled according to the interface  
int desiredWidth = (int)(bitmap.Width * .5); 
Font font = new Font("Arial", 16, FontStyle.Regular); 
SizeF stringSizeF = g.MeasureString(Watermark, font); 
float Ratio = stringSizeF.Width / font.SizeInPoints; 
int requiredFontSize = (int)(desiredWidth / Ratio); 
//  Calculate the position of the point in the picture  
Font requiredFont = new Font("Arial", requiredFontSize, FontStyle.Bold); 
stringSizeF = g.MeasureString(Watermark, requiredFont); 
int x = desiredWidth - (int)(stringSizeF.Width / 2); 
int y = (int)(bitmap.Height * .5) - (int)(stringSizeF.Height / 2); 
g.DrawString(Watermark, new Font("Verdana", requiredFontSize, FontStyle.Bold), brush, new Point(x, y)); 
bitmap.Save(newFilePath, ImageFormat.Jpeg); 
} 
else if (WatermarkType == (int)WatermarkTypeEnum.Image) // Generate image watermarking  
{ 
if (string.IsNullOrEmpty(ImageWartermarkPath)) 
{ 
// The relative file physical path for the image watermark is not specified  
return UploadResultEnum.ImageWartermarkPathNoSpecify; 
} 
fromImg = Image.FromFile(ImageWartermarkPath); 
g.DrawImage(fromImg, new Rectangle(bitmap.Width - fromImg.Width, bitmap.Height - fromImg.Height, fromImg.Width, fromImg.Height), 0, 0, fromImg.Width, fromImg.Height, GraphicsUnit.Pixel); 
bitmap.Save(newFilePath, ImageFormat.Jpeg); 
} 
} 
catch 
{ 
// Failed to upload original file  
return UploadResultEnum.UploadOriginalFileFailure; 
} 
finally 
{ 
if (fromImg != null) 
{ 
fromImg.Dispose(); 
} 
g.Dispose(); 
bitmap.Dispose(); 
} 
} 
#endregion 
this.NewFilePath = newFilePath.Replace("\\", "/"); 
#region  Generate thumbnails of various sizes  
// Generate thumbnails of various sizes  
if (PicSize != null && PicSize.Length > 0) 
{ 
int width, height; 
ArrayList picPathArray = new ArrayList(); 
for (int i = 0; i < PicSize.GetLength(0); i++) 
{ 
width = PicSize[i, 0]; 
height = PicSize[i, 1]; 
Guid tempGuid = Guid.NewGuid(); 
// Thumbnail name  
string thumbnailFileName = physicalPath + tempGuid.ToString() + "_" + width.ToString() + "X" + height.ToString() + fileExtention; 
if (!SaveThumb(sourcefile, width, height, thumbnailFileName)) 
{ 
// Failed to generate thumbnail  
return UploadResultEnum.CreateThumbnailImageFailure; 
} 
picPathArray.Add(thumbnailFileName.Replace("\\", "/")); 
} 
PicPath = (string[])picPathArray.ToArray(typeof(string)); 
} 
#endregion 
// Uploaded successfully  
return UploadResultEnum.Success; 
} 
/// <summary> 
///  Generate thumbnails  
/// </summary> 
/// <param name="sourcefile"></param> 
/// <param name="width"> Generate the width of the thumbnail </param> 
/// <param name="height"> Generate the height of the thumbnail </param> 
/// <param name="thumbnailFileName"> Thumbnail generation path, the absolute physical path with the disk character. </param> 
/// <returns></returns> 
/// <author>Marc</author> 
private bool SaveThumb(HttpPostedFile sourcefile, int width, int height, string thumbnailFileName) 
{ 
bool result = false; 
Image ori_img = Image.FromStream(sourcefile.InputStream); 
int ori_width = ori_img.Width;//650 
int ori_height = ori_img.Height;//950 
int new_width = width;//700 
int new_height = height;//700 
//  Judge the equal proportion here , The formula is as follows:  
if (new_width > ori_width) 
{ 
new_width = ori_width; 
} 
if (new_height > ori_height) 
{ 
new_height = ori_height; 
} 
if ((double)ori_width / (double)ori_height > (double)new_width / (double)new_height) 
{ 
new_height = ori_height * new_width / ori_width; 
} 
else 
{ 
new_width = ori_width * new_height / ori_height; 
} 
Image bitmap = new System.Drawing.Bitmap(new_width, new_height); 
Graphics g = Graphics.FromImage(bitmap); 
try 
{ 
g.SmoothingMode = SmoothingMode.HighQuality; 
g.InterpolationMode = InterpolationMode.High; 
g.Clear(System.Drawing.Color.Transparent); 
g.DrawImage(ori_img, new Rectangle(0, 0, new_width, new_height), new Rectangle(0, 0, ori_width, ori_height), GraphicsUnit.Pixel); 
bitmap.Save(thumbnailFileName, ImageFormat.Jpeg); 
result = true; 
} 
catch 
{ 
result = false; 
} 
finally 
{ 
if (ori_img != null) 
{ 
ori_img.Dispose(); 
} 
if (bitmap != null) 
{ 
bitmap.Dispose(); 
} 
g.Dispose(); 
bitmap.Dispose(); 
} 
return result; 
} 
/// <summary> 
///  Check the file extension  
/// </summary> 
/// <param name="extention"></param> 
/// <returns></returns> 
protected bool CheckExtention(string extention) 
{ 
bool b = false; 
string[] extentions = this.UploadExtention.Split(','); 
for (int i = 0; i < extentions.Length; i++) 
{ 
if (extention.ToLower() == extentions[i].ToLower()) 
{ 
b = true; 
break; 
} 
} 
return b; 
} 
/// <summary> 
///  Back to upload results  
/// </summary> 
/// <param name="result"> The message set </param> 
/// <returns></returns> 
/// <author>marc</author> 
public string Error(int[] result) 
{ 
string s = ""; 
for (int i = 0; i < result.Length; i++) 
{ 
s += " The first " + (i + 1).ToString() + " zhang :"; 
if (result[i] != 1) 
{ 
switch (result[i]) 
{ 
case (int)UploadResultEnum.UploadedObjectIsNull: 
s += " No object to upload was specified "; 
break; 
case (int)UploadResultEnum.ExtentionIsNotAllowed: 
s += " File extensions are not allowed "; 
break; 
case (int)UploadResultEnum.ContentLengthNotWithinTheScope: 
s += " The file size is not limited "; 
break; 
case (int)UploadResultEnum.UploadPhysicalPathNoSpecify: 
s += " The physical save path for the file is not configured or specified "; 
break; 
case (int)UploadResultEnum.ImageWartermarkPathNoSpecify: 
s += " The relative file physical path for the image watermark is not specified "; 
break; 
case (int)UploadResultEnum.StringWatermarkNoSpecify: 
s += " Text without watermark specified "; 
break; 
case (int)UploadResultEnum.UploadOriginalFileFailure: 
s += " Failed to upload original file "; 
break; 
case (int)UploadResultEnum.CreateThumbnailImageFailure: 
s += " Failed to generate thumbnail "; 
break; 
case (int)UploadResultEnum.UnknownError: 
s += " An unknown error "; 
break; 
default: 
break; 
} 
} 
else 
{ 
s += " Uploaded successfully "; 
} 
s += ";\\r\\n"; 
} 
return s; 
} 
/// <summary> 
///  Back to upload results  
/// </summary> 
/// <param name="result"> News value ,int type </param> 
/// <returns></returns> 
/// <author>marc</author> 
public string Error(int result) 
{ 
string s = null; 
switch (result) 
{ 
case (int)UploadResultEnum.UploadedObjectIsNull: 
s += " No object to upload was specified "; 
break; 
case (int)UploadResultEnum.ExtentionIsNotAllowed: 
s += " File extensions are not allowed "; 
break; 
case (int)UploadResultEnum.ContentLengthNotWithinTheScope: 
s += " The file size is not limited "; 
break; 
case (int)UploadResultEnum.UploadPhysicalPathNoSpecify: 
s += " The physical save path for the file is not configured or specified "; 
break; 
case (int)UploadResultEnum.ImageWartermarkPathNoSpecify: 
s += " The relative file physical path for the image watermark is not specified "; 
break; 
case (int)UploadResultEnum.StringWatermarkNoSpecify: 
s += " Text without watermark specified "; 
break; 
case (int)UploadResultEnum.UploadOriginalFileFailure: 
s += " Failed to upload original file "; 
break; 
case (int)UploadResultEnum.CreateThumbnailImageFailure: 
s += " Failed to generate thumbnail "; 
break; 
case (int)UploadResultEnum.UnknownError: 
s += " An unknown error "; 
break; 
case (int)UploadResultEnum.Success: 
s += " Uploaded successfully "; 
break; 
default: 
break; 
} 
return s; 
} 
} 
} 

All of the implementation functions are in this template method.
It mainly defines the "constant property", "enumeration", "upload property", as well as the open method SaveAs(HttpPostedFile sourcefile) and the method to return error messages.
3. Concrete abstract class implementation, very simple, see
 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Web; 
namespace CCNF.Plugin.Upload 
{ 
/// <summary> 
///  Upload a file  
/// </summary> 
/// <creator>Marc</creator> 
public sealed class Upload : UploadAbstract 
{ 
} 
} 

4. Foreground processing page Upload.ashx, note processing page, ashx file.
 
<%@ WebHandler Language="C#" Class="Upload" %> 
using System; 
using System.Web; 
using System.IO; 
public class Upload : IHttpHandler 
{ 
public void ProcessRequest(HttpContext context) 
{ 
HttpResponse response = context.Response; 
HttpRequest request = context.Request; 
HttpServerUtility server = context.Server; 
context.Response.ContentType = "text/plain"; 
HttpPostedFile httpPostedFile = request.Files["FileData"]; 
string uploadpath = request["folder"] + "\\";// server.MapPath(request["folder"] + "\\"); 
if (httpPostedFile != null) 
{ 
CCNF.Plugin.Upload.Upload upload = new CCNF.Plugin.Upload.Upload(); 
upload.SaveFolder = uploadpath; 
upload.PicSize = new int[,] { { 200, 150 } };// To generate thumbnails, please define the size and size of thumbnails 2 Dimensional array  
int result = upload.SaveAs(httpPostedFile); 
if (result == 1) 
{ 
context.Response.Write("1"); 
} 
else 
{ 
throw new Exception(upload.Error(result)); 
// context.Response.Write("0"); 
} 
} 
} 
public bool IsReusable 
{ 
get 
{ 
return false; 
} 
} 
} 

5. The foreground aspx page calls the ashx page
Here, I'm using a third party control, which is not the focus of this article, so I'm just going to say that the name of the control is jquery.uploadify, and you can go to 1 for the code for the js control. Simple to use 1 js package control.
With the js control, the file post uploaded from the page will be sent to the ashx processing file, and ashx will receive the data and start uploading.
Afterword.
1. The upload function is ubiquitous, and the main highlight of this article is to generate multiple thumbnails. For the micro life movement like outdoor mall (http: / / sports. 8 t8x. com /), taobao and other sites, very suitable.
2. I review the design pattern again, review the old and learn something new, and find something new, so I am writing this to comfort you.
About the author
Ma zhiyuan (Marc) graduated from hubei university in 1981 and 2002, and now lives in guangzhou. I learned programming in 2004 and have 8 years of programming experience so far. I have been engaged in the development and design of asp.net B/S for a long time. Strong capabilities in project solutions, project performance and expansion. You can contact me at mazhiyuan1981@163.com.

Related articles: