formdata上傳文件c
『壹』 前端上傳文件的幾種方法
1.表單上傳
最傳統的圖片上傳方式是form表單上傳,使用form表單的input[type=」file」]控制項,打開系統的文件選擇對話框,從而達到選擇文件並上傳的目的。
form表單上傳
表單上傳需要注意以下幾點:
(1).提供form表單,method必須是post。
(2).form表單的enctype必須是multipart/form-data。
javascript學習交流群:453833554
enctype 屬性規定在發送到伺服器之前應該如何對表單數據進行編碼。默認地,表單數據會編碼為 "application/x-www-form-urlencoded"。就是說,在發送到伺服器之前,所有字元都會進行編碼。HTML表單如何打包數據文件是由enctype這個屬性決定的。enctype有以下幾種取值:
application/x-www-form-urlencoded:在發送前編碼所有字元(默認)(空格被編碼為』+』,特殊字元被編碼為ASCII十六進制字元)。
multipart/form-data:不對字元編碼。在使用包含文件上傳控制項的表單時,必須使用該值。
text/plain:空格轉換為 「+」 加號,但不對特殊字元編碼。
默認enctype=application/x-www-form-urlencoded,所以表單的內容會按URL規則編碼,然後根據表單的提交方法:
method=』get』 編碼後的表單內容附加在請求連接後,
method=』post』 編碼後的表單內容作為post請求的正文內容。
『貳』 form表單提交上傳圖片
上傳圖片我首先想到的是利用這個插件,webupload LUploade這類插件大多支持圖片預覽,斷點/分片上傳,功能比較豐富,但是由於後台原因我需要利用form表單進行上傳圖片,所以就整理了一下關於圖片上傳的幾種方式:
1.form表單上傳圖片
表單上傳遇到了一下幾個問題:
(1)進行表單提交時,無法獲取返回值
(2)表單提交會進行頁面刷新
為了解決這個問題,我想到了利用iframe進行解決,在form元素上直接添加target屬性,使提交跳轉頁面直接跳轉到iframe中,阻止頁面進行跳轉,返回結果也會呈現在 iframe框架之中,我們可以去除iframe中的返回值,前提是必須在同一個域名下。這樣我們獲取返回值就會擁有局限性。還好我反降了另外一種方法,jquery中jqueryj.form.js表單提交插件。我們可以直接這樣來獲取表單返回值。
form表單提交注意事項:
(1).提供form表單,method必須是post。
(2).form表單的enctype必須是multipart/form-data。
javascript學習交流群:4538335s's's's'sssssssssssssss54
enctype 屬性規定在發送到伺服器之前應該如何對表單數據進行編碼。默認地,表單數據會編碼為 "application/x-www-form-urlencoded"。就是說,在發送到伺服器之前,所有字元都會進行編碼。HTML表單如何打包數據文件是由enctype這個屬性決定的。enctype有以下幾種取值:
application/x-www-form-urlencoded:在發送前編碼所有字元(默認)(空格被編碼為』+』,特殊字元被編碼為ASCII十六進制字元)。
multipart/form-data:不對字元編碼。在使用包含文件上傳控制項的表單時,必須使用該值。
text/plain:空格轉換為 「+」 加號,但不對特殊字元編碼。
默認enctype=application/x-www-form-urlencoded,所以表單的內容會按URL規則編碼,然後根據表單的提交方法:
method=』get』 編碼後的表單內容附加在請求連接後,
method=』post』 編碼後的表單內容作為post請求的正文內容。
(3).提供input type="file"上傳輸入域。
2.ajax無刷新上傳
ajax和FormData可實現頁面無刷新的文件上傳效果,主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的
FormData介面。通過FormData對象可以更靈活方便的發送表單數據,因為可以獨立於表單使用。如果你把表單的編碼類型設置為multipart/form-data ,則通過FormData傳輸的數據格式和表單通過submit()方法傳輸的數據格式相同。
ajax無刷新上傳
Ajax無刷新上傳的方式,本質上與表單上傳無異,只是把表單里的內容提出來採用ajax提交,並且由前端決定請求結果回傳後的展示結果。
3.各類插件的使用:
webupload LUPloader
『叄』 如何使用formData上傳file數組
可以用數組形式,我貼代碼了
html 部分
<li class="list-group-item disabled select-file-div">
<input type="file" multiple="true" class="input-sm clear-l-r-padding select-file" data-uploadtype="photo"/>
</li>
js部分
var i,
data = new FormData();
...
for (i = 0; i < $('.select-file').files.length; i++) {
data.append('file[]', this.files[i]);
}
...//省略代碼若干...在選擇完成後調用下面$.ajax$.ajax({
url: 'url'
type: "POST",
data: data,
dataType: 'json',
processData: false,// *重要,確認為false
contentType: false,
beforeSend: function () {
... },
success: function (res) {
console.log(res);
},
error: function (res) {
...}
});
php 部分 接收數組
$fileField='file';
$name = $_FILES$fileField;
$tmp_name = $_FILES[$fileField]['tmp_name'];
$size = $_FILES[$fileField]['size'];
$error = $_FILES[$fileField]['error'];
/ 如果是多個文件上傳則$file["name"]會是一個數組 /
if(is_Array($name)){
$errors=array();
/多個文件上傳則循環處理 , 這個循環只有檢查上傳文件的作用,並沒有真正上傳 /
for($i = 0; $i < count($name); $i++){
/設置文件信息 /
if($this->setFiles($name[$i],$tmp_name[$i],$size[$i],$error[$i] )) {
if(!$this->checkFileSize() || !$this->checkFileType()){
$errors[] = $this->getError();
$return=false;
}
}else{
$errors[] = $this->getError();
$return=false;
}
/ 如果有問題,則重新初使化屬性 /
if(!$return)
$this->setFiles();
}
『肆』 [FE] 用 FormData 上傳多個文件到 MultipartFile[] 介面
最近有一個場景,在提交表單的時候,需要實現添加附件的功能,
表單內容要先提交到服務端,創建一個 issue,然後再將附件添加到這個 issue 中。
所以,附件在用戶添加的時候,是 沒有立即上傳 的,
用戶可以隨意在瀏覽器端添加和刪除,issue 創建後再一起上傳。
前端採用的組件庫是 antd ,用到了 upload 組件。
服務端介面是自定義實現的,也許並不支持 antd upload 上傳組件的規范。
服務端接受數據時,使用了 MultipartFile ,這是 Spring 框架中常用的 寫法 。
我們先看看 html input[type=file] 組件默認行為,
點擊 「選擇文件」,瀏覽器會彈出一個窗口,
選中一個文件,點 「打開」,就會觸發 onchange 事件,
在 onchange 事件中,可以通過 e.target.files[0] 拿到剛才上傳的那個 File 對象 。
再來看一下 upload 組件的默認行為,
點擊 「添加」,瀏覽器也會彈出那個選擇文件的窗口,
選中一個文件,點 「打開」,發現上傳失敗了。
打開控制台,看到 upload 組件向 / 這個地址發送了一個 POST 請求,
數據格式如下,
我們可以向 upload 組件傳入 action 參數,修改 POST 請求地址,
但是,選中文件後立即上傳 不符合 我們的場景,我們需要提交表單之後,將多個文件統一上傳。
所以我們得自定義 upload 組件的行為。
upload 組件的有一個 customRequest 屬性( #api ),
它可以配置自定義的上傳行為。
我們的思路是,先將選中後自動上傳的行為取消掉,然後再在提交表單後統一上傳。
取消自動上傳 的實現片段如下,
我們只需要在 customRequest 回調中,調用它的 onSuccess 參數即可。
刪除也是可以用的,
現在我們添加兩個附件,
接著來看前端怎樣將這些附件,統一上傳給服務端,具體實現如下,
可以看到請求成功了(項目中的 url 跟本例稍有不同,下圖只為了示意),
還有幾個需要注意的點:
上文 httpClient.post 實際調用了 XMLHttpRequest 發送請求,可能會遇到 跨域 的問題。
所以在調試上傳介面的時候,需要檢查一下服務端的配置,是否支持跨域請求。
CORS 相關的內容大致如下:
在預檢請求階段,服務端對 OPTIONS 請求的響應頭中會包含 Access-Control-Allow-Origin ,
表明服務端接受該域 http://foo.example 的跨域請求。
註:
這里需要後端實現 OPTIONS 方法,後端框架一般會通過配置方式統一處理(返回 200 或 204,不能是 4xx)。
如果未配置統一處理方式,框架可能會直接返回 404 導致預檢請求失敗,CORS 請求也會失敗。
使用 XMLHttpRequest 發送請求時,也可以攜帶 cookie 信息,
同時 預檢請求中服務端響應頭,也要包含 Access-Control-Allow-Credentials ,否則就不會發送 cookie
對於附帶 cookie 的請求,伺服器不能設置 Access-Control-Allow-Origin 的值為 「 * 」,否則請求將會失敗。
而將 Access-Control-Allow-Origin 的值設置為具體的地址 http://foo.example ,請求才能成功。
我們上傳功能用到了攜帶 cookie 的跨域請求,
可以看到服務端響應頭中確實包含了, Access-Control-Allow-Credentials 和 Access-Control-Allow-Origin 兩個欄位。
Spring: Uploading Files
Spring: org.springframework.web.multipart #MultipartFile
ant-design v4.11.1
Ant Design - Upload #API
MDN: CORS