企業級檔案上傳需兼顧安全、效能、可維護性。本文提供完整上傳處理流程:驗證 → 重命名 → 存檔 → 縮圖 → 記錄 DB → 回應。
<form id="form1" runat="server" enctype="multipart/form-data">
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="ButtonUp" runat="server" Text="上傳" OnClick="ButtonUp_Click" />
<asp:Label ID="LabelTitle2" runat="server" Text="*上傳檔案不能超過 2MB" ForeColor="Red" />
<br />原始檔名:<span id="FileName" runat="server" />
<br />儲存路徑:<span id="SaveDir" runat="server" />
<br />縮圖路徑:<span id="sSaveDir" runat="server" />
<br />檔案類型:<span id="FileType" runat="server" />
<br />檔案大小:<span id="FileLength" runat="server" />
<br />副檔名:<span id="FileExtention" runat="server" />
<br />上傳時間:<span id="UpDateTime" runat="server" />
<br /><asp:Image ID="Image1" runat="server" />
</form>
protected void ButtonUp_Click(object sender, EventArgs e)
{
if (!FileUpload1.HasFile) { ShowAlert("請選擇檔案"); return; }
// 1. 基本資訊
string origName = FileUpload1.FileName;
long fileSize = FileUpload1.PostedFile.ContentLength;
string contentType = FileUpload1.PostedFile.ContentType;
string ext = Path.GetExtension(origName).ToUpper();
FileName.InnerHtml = origName;
UpDateTime.InnerHtml = DateTime.Now.ToShortDateString();
FileLength.InnerHtml = FormatFileSize(fileSize);
FileType.InnerHtml = contentType;
FileExtention.InnerHtml = ext;
// 2. 大小限制 (2MB)
if (fileSize > 2 * 1024 * 1024) { ShowAlert("檔案超過 2MB 限制"); return; }
// 3. 類型驗證 (僅允許 JPG)
if (ext != ".JPG" && ext != ".JPEG") { ShowAlert("僅允許 JPG 格式"); return; }
// 4. 產生唯一檔名:域名-時間戳-副檔名
string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff").Replace(".", "-");
string saveName = $"www.MWO.Com-{timestamp}{ext}";
string thumbName = $"www.MWO.Com-{timestamp}{ext}";
string savePath = Server.MapPath("~/photo/") + saveName;
string thumbPath = Server.MapPath("~/SPhoto/") + thumbName;
SaveDir.InnerHtml = savePath;
sSaveDir.InnerHtml = thumbPath;
// 5. 生成高品質縮圖 (118x90)
MakeHighQualityThumbnail(FileUpload1.PostedFile, thumbPath, 118, 90);
// 6. 儲存原圖
FileUpload1.SaveAs(savePath);
// 7. 寫入資料庫
PhotoInfo info = new PhotoInfo
{
Organization = "5173",
PicName = origName,
ServerName = "GLSDB",
Cdate = DateTime.Now,
Exp = ext,
Flag = 0,
GameNickName = "Bruce",
MoonStar = 0,
ShowIndex = 0,
SPicHttpAddr = thumbPath,
Type = 0,
Vote = 0,
PicHttpAddr = savePath
};
new PhotoDAO().Insert(info);
ShowAlert("上傳成功");
Image1.ImageUrl = "~/SPhoto/" + thumbName; // 即時預覽
}
// 高品質縮圖:保持比例、雙三次插值、平滑模式
public void MakeHighQualityThumbnail(HttpPostedFile postedFile, string savePath, double maxW, double maxH)
{
using (Image src = Image.FromStream(postedFile.InputStream, true))
{
double ratio = Math.Min(maxW / src.Width, maxH / src.Height);
int nW = (int)(src.Width * ratio);
int nH = (int)(src.Height * ratio);
using (Bitmap bmp = new Bitmap(nW, nH))
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality;
g.Clear(Color.White);
g.DrawImage(src, new Rectangle(0, 0, nW, nH), new Rectangle(0, 0, src.Width, src.Height), GraphicsUnit.Pixel);
bmp.Save(savePath, ImageFormat.Jpeg);
}
}
}
private string FormatFileSize(long bytes)
{
if (bytes < 1024) return $"{bytes} Bytes";
if (bytes < 1024 * 1024) return $"{bytes / 1024} KB";
return $"{bytes / 1024 / 1024} MB";
}
private void ShowAlert(string msg) => Response.Write($"");
IAsyncResult / Hangfire / 背景服務,避免阻塞 Web 執行緒。
6. 資料庫參數化:PhotoDAO.Insert 內部使用 SqlParameter,防 SQL 注入。
此流程已在生產環境穩定運行,可直接作為企業級上傳模組基礎擴充。