formData批量上傳的多種實現
最近專案需要批量上傳附件,查了下資料,網上很多但看著一臉懵,只貼部分程式碼,介紹也不詳細,這裡記錄一下自己的採坑與多種實現,以免以後忘記。
這裡先介紹下FormData物件,以下內容摘自:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
XMLHttpRequest Level 2添加了一個新的介面 FormData
.利用 FormData物件
,我們可以通過JavaScript用一些鍵值對來模擬一系列表單控制元件,我們還可以使用XMLHttpRequest的 ofollow,noindex" target="_blank"> send()
方法來非同步的提交這個"表單".比起普通的ajax,使用 FormData
的最大優點就是我們可以非同步上傳一個二進位制檔案.
在我的 自定義input檔案上傳樣式 裡就已經實現裡單檔案上傳,並且實現了自定義input樣式;如果構造FormData物件是傳入表單js物件,formData會自動注入表單裡的值;如果是new一個空物件,然後手動append的表單型別為file時要注意:這裡append進去的是File物件,而不是FileList物件
先看一下大概效果:
controller有兩種方法:三種方式調的都是用一個介面
/** * 批量上傳 */ @PostMapping("upload") public ResultModel<List<AttachmentVo>> upload(HttpServletRequest request, @RequestParam("applyId") String applyId){ List<MultipartFile> multipartFileList = ((MultipartHttpServletRequest) request).getFiles("attachment"); System.out.println(multipartFileList.size()); System.out.println(applyId); return null; } /** * 批量上傳2 (推薦使用) */ @PostMapping("upload2") public ResultModel<List<AttachmentVo>> upload2(MultipartFile[] attachment,@RequestParam("applyId") String applyId){ System.out.println(attachment.length); System.out.println(applyId); return null; }
方式1
點選Add,追加一個input,點選Delete,刪除一個input,點選叉號也可以刪除對應的input,需要單獨為每個input選擇檔案
效果
html
<form id="attachments" enctype="multipart/form-data" class="form-horizontal nice-validator n-yellow" novalidate="novalidate"> <div class='form-body'> <div class='form-group'> <label class="control-label col-md-1">附件管理:</label> <div class="col-md-4"> <button id="attachmentAddBtn" type="button" class="btn btn-default">Add Attachment</button> <button id="attachmentDeleteBtn" type="button" class="btn btn-default">Delete Attachment</button> <button id="attachmentUploadBtn" type="button" class="btn btn-default">Upload</button> </div> </div> <div class='form-group'> <label class="control-label col-md-1">附件上傳:</label> <div id="attachmentInputs" class="col-md-3"> </div> </div> </div> </form>
js
//attachment-remove $("#attachmentInputs").on("click", ".attachment-remove", function (even) { $(this).prev().remove();//刪除上一個兄弟節點 $(this).remove();//刪除自己 }); //add but $("#attachmentAddBtn").click(function (even) { //name值一樣就可以 $("#attachmentInputs").append("<input name=\"attachment\" type=\"file\" class=\"form-control input-attachment\"/><i class=\"fa fa-times attachment-remove\"></i>"); }); //delete $("#attachmentDeleteBtn").click(function (even) { var files = $("#attachmentInputs input[type='file']"); files.each(function (index, element) { //從最下面開始刪除,至少保留一個 if (!(index === 0) && index === (files.length - 1)) { $(element).next().remove(); $(element).remove(); } }); }); //upload $("#attachmentUploadBtn").click(function (even) { //1、通過HTML表單建立FormData物件 自動注入 // var formData = new FormData($("#attachments")[0]); //2、從零開始建立FormData物件 手動注入 var formData = new FormData(); //注入 name=file var files = $("#attachmentInputs input[type='file']"); for (var i = 0; i < files.length; i++) { //注意:這裡append進去的是File物件,而不是FileList物件 formData.append("attachment", files[i].files[0]); } //注入name=text formData.append("applyId", "123456"); console.log(formData.getAll("attachment")); //執行上傳 $.ajax({ url: ctx + "/attachment/upload2", type: "post", data: formData, processData: false, contentType: false, success: function (data) { }, error: function (e) { } }); }); //add one input $("#attachmentAddBtn").click();
方式2
第二種方式只有一個input,用的是multiple="multiple"屬性,可以再彈窗裡選擇多個檔案提交,如果再加工一下,也做成第三種一樣,展示出檔名,同時可以刪除對應的檔案
效果
html
<form id="attachments2" enctype="multipart/form-data" class="form-horizontal" novalidate="novalidate"> <div class='form-body'> <div class='form-group'> <label class="control-label col-md-1">附件管理:</label> <div class="col-md-4"> <button id="attachmentUploadBtn2" type="button" class="btn btn-default">Upload</button> </div> </div> <div class='form-group'> <label class="control-label col-md-1">附件上傳:</label> <div id="attachmentInputs2" class="col-md-3"> <input name="attachment" type="file" class="form-control input-attachment" multiple="multiple"/> </div> </div> </div> </form>
js
//upload2 $("#attachmentUploadBtn2").click(function (even) { //1、通過HTML表單建立FormData物件 自動注入 // var formData = new FormData($("#attachments2")[0]); //2、從零開始建立FormData物件 手動注入 var formData = new FormData(); //注入 name=file var files = $("#attachmentInputs2 input[type='file']"); for (var i = 0; i < files[0].files.length; i++) { formData.append("attachment", files[0].files[i]); } //注入name=text formData.append("applyId", "123456"); console.log(formData.getAll("attachment")); //執行上傳 $.ajax({ url: ctx + "/attachment/upload2", type: "post", data: formData, processData: false, contentType: false, success: function (data) { }, error: function (e) { } }); });
方式3
定義了一個隱藏的input,並將Select File按鈕的click與input的click對等,點選按鈕相當於點選input,彈出選擇檔案對話方塊,監聽了input的change事件,將選擇的file物件push到全域性陣列變數attachmentArray中,點選Upload時再遍歷注入到formData中
效果
html
<form id="attachments3" enctype="multipart/form-data" class="form-horizontal" novalidate="novalidate"> <div class='form-body'> <div class='form-group'> <label class="control-label col-md-1">附件管理:</label> <div class="col-md-4"> <button id="selectFile" type="button" class="btn btn-default">Select File</button> <button id="attachmentUploadBtn3" type="button" class="btn btn-default">Upload</button> </div> </div> <div class='form-group'> <label class="control-label col-md-1">附件上傳:</label> <input id="attachmentInputs3" type="file" style="display: none;"/> <div id="attachmentText3" class="col-md-3"> </div> </div> </div> </form>
js
//存放file物件 var attachmentArray = []; //attachment-remove $("#attachmentText3").on("click", ".attachment-remove", function (even) { //刪除attachmentArray資料 attachmentArray.splice($(this).data("index"), 1); //刪除html物件 $(this).prev().prev().remove(); $(this).prev().remove(); $(this).remove(); }); //Select File $("#selectFile").click(function (even) { // 獲取input $("#attachmentInputs3").click(); }); //input change $("#attachmentInputs3").change(function (even) { // 獲取input var fileName = $(this).val(); var file = $(this)[0].files[0]; //是否選擇了檔案 if (fileName) { attachmentArray.push(file); $("#attachmentText3").append("<div><p class='attachment-text-p'>" + fileName + "</p><i data-index='" + (attachmentArray.length - 1) + "' class=\"fa fa-times attachment-remove\"></i></div>") } }); //upload3 $("#attachmentUploadBtn3").click(function (even) { //這裡只能手動注入 var formData = new FormData(); //遍歷資料,手動注入formData for (var i = 0; i < attachmentArray.length; i++) { formData.append("attachment", attachmentArray[i]); } formData.append("applyId", "123456"); console.log(formData.getAll("attachment")); //執行上傳 $.ajax({ url: ctx + "/attachment/upload", type: "post", data: formData, processData: false, contentType: false, success: function (data) { }, error: function (e) { } }); });
最後看一下file資料、請求頭、還有振奮人心的後臺成功接參圖
file資料
請求頭
成功接參