利用FormData對象實現AJAX文件上傳功能及後端實現

mark
包括HTML基礎設置、CSS界面優化、JS利用FormData對象和AJAX進行上傳、後端接收文件並存儲到指定路徑以及刪除文件操做。

FE

HTML

基礎的設置:php

<form enctype="multipart/form-data">
  <input id="file" type="file" multiple="multiple" name="file" accept="...">
  <input type="submit" value="上傳">
</form>
複製代碼

Form的enctype屬性

enctype這個屬性管理的是表單的MIME編碼,它一共有三個屬性:html

描述
application/x-www-form-urlencoded 在發送前編碼全部字符(默認)
multipart/form-data 不對字符編碼,用來制定傳輸數據的特殊類型,如mp三、jpg
text/plain 純文本傳輸

所以,傳輸完整的文件數據須要multipart/form-data屬性。程序員

Input

value

保存了用戶指定的文件的名稱。web

type="file"

設置input類型爲file。數據庫

multiple="multiple"

可多選,不設置爲單選。後端

accept="..."

設置可選文件的MIME_type。在設置以後點擊選擇文件按鈕會默認顯示符合設置的MIME_type的文件(存在兼容性)。具體的文件類型對應的MIME類型能夠搜索到,這裏列出我用到的類型:數組

文件類型 MIME類型
.txt text/plain
.pdf application/pdf
.doc application/msword
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
.xls application/vnd.ms-excel
.ppt application/vnd.ms-powerpoint
.pptx application/vnd.openxmlformats-officedocument.presentationml.presentation

效果

mark

太醜,不能忍...瀏覽器

CSS

默認界面會在選擇文件按鈕後會跟一個顯示文件名的文本區域,選擇文件按鈕沒法編輯。 我修改的方法是將input框隱藏,再設置一個lable標籤使用戶點擊lable標籤時觸發選擇文件按鈕。安全

<label for="file">選擇文件</label>
複製代碼

效果

mark

JS

在使用from提交時,瀏覽器會向服務器發送選中的文件的內容而不單單是發送文件名。服務器

爲安全起見,<input type="file">即file-upload 元素不容許 HTML 做者或 JavaScript 程序員指定一個默認的文件名。HTML value 屬性被忽略,而且對於此類元素來講,value屬性是隻讀的,這意味着只有用戶能夠輸入一個文件名。當用戶選擇或編輯一個文件名時,file-upload 元素觸發 onchange 事件句柄。

利用form提交會致使頁面刷新,體驗很差,因此使用AJAX進行文件上傳是個不錯的選擇。但這須要咱們本身來組織經過POST請求發送的內容。

FormData對象

經過FormData對象能夠組裝一組用 XMLHttpRequest發送請求的鍵/值對。它能夠更靈活方便的發送表單數據,由於能夠獨立於表單使用。若是你把表單的編碼類型設置爲multipart/form-data ,則經過FormData傳輸的數據格式和表單經過submit() 方法傳輸的數據格式相同。 —— MDN web docs

建立FormData對象

let formData = new FormData();
複製代碼

向實例化對象中添加文件字段

let myFile = document.getElementById('file');
// myFile.file[0]爲第一個文件(單選),多個文件(多選)則要循環添加
formData.append('myFile', myFile.files[0]);
複製代碼
console.log(myFile.files[0]);
複製代碼

mark

其中size屬性單位是byte(字節),即b。

添加自定義字段

formData.append('username', 'simmzl');
複製代碼

AJAX發送

let request = new XMLHttpRequest();
request.open("POST", "http://foo.com/foo.php");
request.send(formData);
複製代碼

不使用FromData對象

不使用FormData對象的狀況下,須要經過AJAX序列化和提交表單 : Using nothing but XMLHttpRequest

PHP

接收

全局數組 $_FILES,第一個參數是表單的 input name,第二個下標是 "name", "type", "size", "tmp_name" 或 "error"。能夠根據這些屬性作相關限制,如限制文件大小、文件類型等

描述
name 文件名
type 文件的MIME類型
size 以字節Byte爲單位的文件大小
tmp_name PHP接收文件會存爲暫時文件,如需保存到指定路徑還要移動這個暫時文件才能夠
error 1-7表明7種不一樣錯誤類別以及0表明成功

error: 成功:0(UPLOAD_ERR_OK) 失敗:

  1. 超過了配置文件上傳文件的大小
  2. 超過了表單設置上傳文件的大小
  3. 文件部分被上傳
  4. 沒有文件被上傳
  5. 沒有找到臨時目錄
  6. 文件不可寫
  7. 因爲PHP的擴展程序中斷了文件上傳

驗證

上傳文件是經過POST發送的,is_uploaded_file(file)函數能夠判斷指定的文件是不是經過 HTTP POST 上傳的,返回布爾值。

該函數能夠用於確保惡意的用戶沒法欺騙腳本去訪問本不能訪問的文件,例如 /etc/passwd。 這種檢查顯得格外重要,若是上傳的文件有可能會形成對用戶或本系統的其餘用戶顯示其內容的話。

保存

上傳的文件暫存在tmp_name中,須要使用move_uploaded_file(file,newlocation)將上傳的文件移動到指定路徑,返回布爾值。

if( move_uploaded_file($tmp_name, $destination) ) {
  echo "文件上傳成功";
}else{
  echo "文件移動失敗";
}
複製代碼

刪除

使用unlink(filepath)刪除文件,參數是文件路徑。

拓展功能

固然除了接收、驗證、保存和刪除這四個基本操做外,還能夠添加諸如將文件路徑存入數據庫、生成文件列表等功能,視需求而定。

最初發表於blog.simmzl.cn

相關文章
相關標籤/搜索