| 方案 | 優點 | 缺點 |
|---|---|---|
| jQuery File Upload | jQuery 異步上傳、高度可定制 | IE9 不支援預覽、不支援多檔選取 |
| CFUpdate | JS+Flash、相容性好、功能完整 | 樣式固定、難以深度定制 |
| SWFUpload | Flash+jQuery、按鈕/樣式可完全自訂、事件豐富 | 需 Flash Player(已淘汰),現代專案建議改用 HTML5 |
本文以 SWFUpload 為例展示核心流程,現代專案請參考 input[type=file] + FileReader + FormData 的純 HTML5 方案。
Thumbnial.cspublic static class Thumbnial
{
public static Image GetThumbnail(Image src, int targetW, int targetH, bool cropCenter)
{
double wScale = (double)src.Width / targetW;
double hScale = (double)src.Height / targetH;
double scale = Math.Min(wScale, hScale); // 等比縮放至覆蓋目標區域
int interimW = (int)Math.Floor(src.Width / scale);
int interimH = (int)Math.Floor(src.Height / scale);
using (Bitmap interim = new Bitmap(interimW, interimH))
using (Graphics g = Graphics.FromImage(interim))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, interimW, interimH);
if (!cropCenter) return new Bitmap(interim); // 僅縮放
// 中心裁切
int x = (interimW - targetW) / 2;
int y = (interimH - targetH) / 2;
Bitmap final = new Bitmap(targetW, targetH);
using (Graphics fg = Graphics.FromImage(final))
{
fg.InterpolationMode = InterpolationMode.HighQualityBicubic;
fg.DrawImage(interim, 0, 0, new Rectangle(x, y, targetW, targetH), GraphicsUnit.Pixel);
}
return final;
}
}
}
Upload.ashxpublic class Upload : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
ctx.Response.ContentType = "text/plain";
try
{
string id = Guid.NewGuid().ToString();
HttpPostedFile file = ctx.Request.Files["Filedata"];
using (Image orig = Image.FromStream(file.InputStream))
{
// 儲存原圖
orig.Save(ctx.Server.MapPath($"~/Files/{id}.jpg"));
// 產生並儲存縮略圖 200x150 裁切
Image thumb = Thumbnial.GetThumbnail(orig, 200, 150, true);
string thumbPath = ctx.Server.MapPath($"~/Files/Files200/{id}.jpg");
thumb.Save(thumbPath);
// 回傳相對路徑供前端預覽
ctx.Response.Write($"Files/Files200/{id}.jpg");
}
}
catch (Exception ex)
{
ctx.Response.StatusCode = 500;
ctx.Response.Write("上傳失敗:" + ex.Message);
}
}
public bool IsReusable => false;
}
Mood.aspx 關鍵 JSvar swfu;
function SetSwf() {
swfu = new SWFUpload({
upload_url: "Upload.ashx",
file_size_limit: "20 MB",
file_types: "*.jpg;*.png;*.jpeg;*.bmp",
file_types_description: "Image Files",
file_upload_limit: "0",
button_image_url: "/Style/Image/4-16.png",
button_placeholder_id: "divBtn",
button_width: 26,
button_height: 26,
flash_url: "/swfupload/swfupload.swf",
file_queue_error_handler: fileQueueError,
file_dialog_complete_handler: fileDialogComplete,
upload_success_handler: uploadSuccess,
upload_complete_handler: uploadComplete,
upload_error_handler: uploadError
});
}
function fileDialogComplete(numSelected, numQueued) {
if (numQueued > 0) {
$("#divImgs").show();
for (var i = 0; i < numQueued; i++)
$("#ulUpload").append(`<li id="li${i}"><img class="imgload" src="/style/image/loading.gif" /></li>`);
this.startUpload();
}
}
function uploadSuccess(file, serverData) {
var idx = file.id.substr(file.id.lastIndexOf('_') + 1);
$(`#li${idx}`).html(`<img src="${serverData}" />`);
}
function uploadComplete(file) {
if (this.getStats().files_queued > 0) this.startUpload();
}
function uploadError(file, code, msg) {
var idx = file.id.substr(file.id.lastIndexOf('_') + 1);
$(`#li${idx}`).html(`<img src="/style/image/imgerror.png" />`);
}
Flash 已於 2020 年停止支援,新專案請採用:
<input type="file" multiple accept="image/*"> 選取多圖FileReader.readAsDataURL() 即時本地預覽(無需上傳)canvas.toBlob() 前端壓縮/裁切縮略圖FormData + fetch/axios 非同步上傳