圖片上傳元件webuploader
阿新 • • 發佈:2018-12-19
前端元件webuploader
當時也是搞了很久參考這種demo,但是沒記、現在事後大致總結下。直接上大概程式碼(我使用asp.net MVC來做的):
執行順序:(get)Record/Add——Add.cshtml頁面,點選確認上傳執行上傳圖片,可多選——(post)Photo/UploadPhotos,完成圖片上傳。多圖分別執行post介面上傳、1張圖失敗可能不會有提示;返回圖片url儲存在頁面的隱藏欄位內——(post)Record/Add儲存整個實體資訊,圖片url解析(用|或;)儲存
1 public ActionResult Add()View Code2 { 3 return View(); 4 } 5 6 [HttpPost] 7 public JsonResult Add(string key1, string key2, string photoUrlSplits, int typeId = 1, string remark = "") 8 { 9 if (key1.IsNullOrWhiteSpace() || photoUrlSplits.IsNullOrWhiteSpace() || photoUrlSplits.Length < 3) 10 return Json(new BaseResponse(ApiCodeEnum.ParamError.GetHashCode(), "引數錯誤")); 11 12 var photoUrls = photoUrlSplits.Trim(';').Split(';').ToList(); 13 _service.SaveRecord(CurrentUser, key1, key2, photoUrls, typeId, remark); 14 return Json(new BaseResponse());15 }
1 public class PhotoController : BaseControllerWithUser 2 { 3 private readonly PhotoService _service = new PhotoService(); 4 5 static string urlPath = string.Empty; 6 7 public PhotoController() 8 { 9 var applicationPath = VirtualPathUtility.ToAbsolute("~") == "/" ? "" : VirtualPathUtility.ToAbsolute("~"); 10 urlPath = applicationPath + "/Upload"; 11 } 12 13 public JsonResult UploadPhotos(string id, string name, string type, string lastModifiedDate, int size, HttpPostedFileBase file) 14 { 15 string filePathName = string.Empty; 16 17 string localPath = Path.Combine(HttpRuntime.AppDomainAppPath, "Upload"); 18 if (Request.Files.Count == 0) 19 { 20 return Json(new { jsonrpc = 2.0, error = new { code = 102, message = "儲存失敗" }, id = "id" }); 21 } 22 23 string ex = Path.GetExtension(file.FileName); 24 filePathName = Guid.NewGuid().ToString("N") + ex; 25 if (!System.IO.Directory.Exists(localPath)) 26 { 27 System.IO.Directory.CreateDirectory(localPath); 28 } 29 file.SaveAs(Path.Combine(localPath, filePathName)); 30 31 return Json(new 32 { 33 jsonrpc = "2.0", 34 id = id, 35 filePath = urlPath + "/" + filePathName 36 }); 37 38 //_service.UploadPhotos(); 39 //return Json(""); 40 } 41 42 }View Code
前端頁面程式碼:
1 @using OuymxPhotoRecordSystem.Web.Service 2 @{ 3 Layout = null; 4 } 5 6 <!DOCTYPE html> 7 <html> 8 <head> 9 <meta name="viewport" content="width=device-width" /> 10 <title>上傳圖片資料</title> 11 @*<script src="../../js/plugins/jQuery/jquery-2.2.3.min.js"></script>*@ 12 <script src="/Scripts/jquery-1.8.2.min.js"></script> 13 <link href="/CSS/webuploader.css" rel="stylesheet" /> 14 <script src="/Scripts/webuploader.js"></script> 15 <link href="/CSS/bootstrap.min.css" rel="stylesheet" /> 16 <link href="/CSS/style.css" rel="stylesheet" /> 17 <link href="/CSS/demo.css" rel="stylesheet" /> 18 <link href="/CSS/font-awesome.css" rel="stylesheet" /> 19 20 <script src="/js/plugins/layer/layer.js"></script> 21 </head> 22 <body> 23 @using (Html.BeginForm("Add", "Record", FormMethod.Post)) 24 { 25 <table class="tc_table_cp" border="0"> 26 <tr> 27 <td width="104">圖片上傳</td> 28 <td colspan="3"> 29 <div id="fileList"> 30 31 </div> 32 <div class="cp_img_jia" id="filePicker"></div> 33 <input id="photoUrlSplits" name="photoUrlSplits" type="hidden" value="" /> 34 <button id="ctlBtn" class="btn btn-default">開始上傳</button> 35 </td> 36 </tr> 37 @*空的行,主要為了顯示上傳失敗的文字提醒*@ 38 <tr> 39 <td width="104"></td> 40 <td colspan="3"> 41 </td> 42 </tr> 43 @*上傳按鈕和隱藏控制元件移到前面去了*@ 44 @*<tr> 45 <td width="104"></td> 46 <td colspan="3"> 47 <input id="photoUrlSplits" name="photoUrlSplits" type="hidden" value="" /> 48 <button id="ctlBtn" class="btn btn-default">開始上傳</button> 49 </td> 50 </tr>*@ 51 <tr> 52 <td>主鍵1</td> 53 <td>@Html.TextBox("key1")</td> 54 </tr> 55 <tr> 56 <td>主鍵2</td> 57 <td>@Html.TextBox("key2")</td> 58 </tr> 59 <tr> 60 <td>型別</td> 61 <td>@Html.DropDownList("typeId", WebMvcHelper.GetPhotoTypes())</td> 62 </tr> 63 <tr> 64 <td>備註</td> 65 <td>@Html.TextBox("remark")</td> 66 </tr> 67 <tr> 68 <td></td> 69 <td> 70 <input id="btnSubmit" type="submit" style="width: 120px;" value="提交儲存" disabled="disabled" title="先上傳圖片後才能提交儲存"/> 71 </td> 72 </tr> 73 </table> 74 } 75 </body> 76 </html> 77 78 <script type="text/javascript"> 79 80 $("#btnSubmit").click(function (event) { 81 event.preventDefault(); 82 83 var photoUrlSplits = $('#photoUrlSplits').val(); 84 var key1 = $('#key1').val(); 85 if (photoUrlSplits == null || photoUrlSplits.length <= 3 || key1 == null || key1 == '') { 86 layer.msg('儲存失敗,原因:主鍵不得為空,待上傳圖片不得為空', { icon: 2, time: 0, closeBtn: 1 }, function () { 87 //no-op 88 }); 89 return; 90 } 91 $.ajax({ 92 type: 'POST', 93 url: '@Url.Action("Add")', 94 data: { 'photoUrlSplits': photoUrlSplits, 'key1': key1, 'key2': $('#key2').val(), 'typeId': $("#typeId").val(), 'remark': $('#remark').val(), }, 95 success: function (data) { 96 if (data.code == 0) { 97 layer.msg('儲存成功', { icon: 1, time: 1000 }, function () { 98 parent.layer.closeAll(); //成功則關閉自身layer 99 //window.parent.location.reload(); //無需執行,因為Index父頁面已定義關閉本layer時自動執行 100 }); 101 } 102 else { 103 layer.msg('儲存失敗,原因:' + data.message, { icon: 2, time: 0, closeBtn: 1 }, function () { 104 //no-op 105 }); 106 } 107 }, 108 dataType: 'json' 109 }); 110 }); 111 112 var applicationPath = window.applicationPath === "" ? "" : window.applicationPath || "../../"; 113 $(function () { 114 var $ = jQuery, 115 $list = $('#fileList'), 116 // 優化retina, 在retina下這個值是2 117 ratio = window.devicePixelRatio || 1, 118 // 縮圖大小 119 thumbnailWidth = 90 * ratio, 120 thumbnailHeight = 90 * ratio, 121 // Web Uploader例項 122 uploader; 123 uploader = WebUploader.create({ 124 // 選完檔案後,是否自動上傳。 125 auto: false, 126 disableGlobalDnd: true, 127 // swf檔案路徑 128 swf: applicationPath + '/Script/Uploader.swf', 129 // 檔案接收服務端。 130 server: applicationPath + '/Photo/UploadPhotos', 131 // 選擇檔案的按鈕。可選。 132 // 內部根據當前執行是建立,可能是input元素,也可能是flash. 133 pick: '#filePicker', 134 //只允許選擇圖片 135 accept: { 136 title: 'Images', 137 extensions: 'gif,jpg,jpeg,bmp,png', 138 mimeTypes: 'image/jpg,image/jpeg,image/png,image/bmp' 139 } 140 }); 141 142 // 當有檔案新增進來的時候 143 uploader.on('fileQueued', function (file) { 144 var $li = $( 145 '<div id="' + file.id + '" class="cp_img">' + 146 '<img>' + 147 '<div class="cp_img_jian"></div></div>' 148 ), 149 $img = $li.find('img'); 150 // $list為容器jQuery例項 151 $list.append($li); 152 // 建立縮圖 153 // 如果為非圖片檔案,可以不用呼叫此方法。 154 // thumbnailWidth x thumbnailHeight 為 100 x 100 155 uploader.makeThumb(file, function (error, src) { 156 if (error) { 157 $img.replaceWith('<span>不能預覽</span>'); 158 return; 159 } 160 161 $img.attr('src', src); 162 }, thumbnailWidth, thumbnailHeight); 163 }); 164 165 // 檔案上傳過程中建立進度條實時顯示。 166 uploader.on('uploadProgress', function (file, percentage) { 167 var $li = $('#' + file.id), 168 $percent = $li.find('.progress span'); 169 170 // 避免重複建立 171 if (!$percent.length) { 172 $percent = $('<p class="progress"><span></span></p>') 173 .appendTo($li) 174 .find('span'); 175 } 176 177 $percent.css('width', percentage * 100 + '%'); 178 }); 179 180 // 檔案上傳成功,給item新增成功class, 用樣式標記上傳成功。 181 uploader.on('uploadSuccess', function (file, response) { 182 $('#' + file.id).addClass('upload-state-done'); 183 $("#photoUrlSplits").val($("#photoUrlSplits").val() + response.filePath + ";");//"/Upload/9bd17b72a61043cf857fb112df3c3cf1.png" 184 //alert("uploadSuccess"); 185 }); 186 187 // 檔案上傳失敗,顯示上傳出錯。 188 uploader.on('uploadError', function (file) { 189 var $li = $('#' + file.id), 190 $error = $li.find('div.error'); 191 192 // 避免重複建立 193 if (!$error.length) { 194 $error = $('<div class="error"></div>').appendTo($li); 195 } 196 $error.text('上傳失敗'); 197 }); 198 199 // 完成上傳完了,成功或者失敗,先刪除進度條。 200 uploader.on('uploadComplete', function (file) { 201 $('#' + file.id).find('.progress').remove(); 202 //alert("uploadComplete"); 203 }); 204 205 //所有檔案上傳完畢 206 uploader.on("uploadFinished", function () 207 { 208 //提交表單 209 //alert("uploadFinished"); 210 211 if ($("div.error").length > 0) { 212 $("#btnSubmit").attr("disabled"); 213 //alert("部分檔案上傳失敗,可能是檔案過大或檔案格式不正確。請排查或諮詢管理員!"); 214 layer.msg("部分檔案上傳失敗,可能是檔案過大或檔案格式不正確。請排查或諮詢管理員!", { icon: 2, time: 0, closeBtn: 1 }); 215 } 216 else { 217 $("#btnSubmit").removeAttr("disabled"); 218 //alert("所有檔案上傳完畢,請檢查是否有錯誤,若全部正確請提交"); 219 220 layer.msg("所有檔案上傳完畢,請檢查是否有錯誤,若全部正確請提交!", { icon: 1, time: 4000, closeBtn: 1 }); 221 } 222 }); 223 224 //開始上傳 225 $("#ctlBtn").click(function () { 226 uploader.upload(); 227 228 event.preventDefault(); 229 }); 230 //以下方法原計劃實現:滑鼠移上去顯示刪除按鈕,移出則不顯示。原demo的live程式碼可實現、但live在jq1.9已被刪除、新的on()做不到對未來元素、指定某未來元素的控制。而本AdminLTEd需要需要jq2.2 231 // 232 //1. 233 //$(document).on("mouseover", ".cp_img_jian", function () { 234 // //此處的$(this)指$( "#testDiv"),而非$(document) 235 // $(this).show(); 236 //}); 237 238 //2. 239 //$(document).on("mouseout", ".cp_img_jian", function () { 240 // //此處的$(this)指$( "#testDiv"),而非$(document) 241 // $(this).hide(); 242 //}); 243 244 //3. 245 //$('#fileList').on('mouseover', function (e) { 246 // $('.cp_img_jian').show(); 247 //}); 248 //$('#fileList').on('mouseout', function (e) { 249 // $('.cp_img_jian').hide(); 250 //}); 251 252 //4. 253 //$(".cp_img").mouseover(function () { 254 // alert("mouseover"); 255 //}); 256 //$(".cp_img").mouseout(function () { 257 // alert("mouseout"); 258 //}); 259 260 //5. 261 //顯示刪除按鈕 262 $(".cp_img").live("mouseover", function () 263 { 264 $(this).children(".cp_img_jian").css('display', 'block'); 265 }); 266 //隱藏刪除按鈕 267 $(".cp_img").live("mouseout", function () { 268 $(this).children(".cp_img_jian").css('display', 'none'); 269 }); 270 //執行刪除方法 271 $list.on("click", ".cp_img_jian", function () 272 { 273 var Id = $(this).parent().attr("id"); 274 uploader.removeFile(uploader.getFile(Id,true)); 275 $(this).parent().remove(); 276 }); 277 278 }); 279 280 </script>View Code
效果圖:
不足(都不是大問題):
1.圖片是單個單個上傳的、沒有分片,可能會速度慢
2.單個圖片失敗可能會沒有提示
3.僅在點選“上傳圖片”後可定點刪除圖片,不能在點選“上傳圖片”前刪除。不過這個不是重點問題不大