如何使用 XMLHttpRequest (XHR) 和 Node.js 上傳文件
文件上傳是現代 Web 應用程序中最常見的功能。許多應用程序允許用戶上傳頭像或附件來執行一些後端任務。編寫代碼以將文件異步上傳到服務器看起來是一項具有挑戰性的任務。
在本文中,我將解釋如何構建 HTML 表單,使用 JavaScript 將選定的文件發送到服務器 ,並在Node.js中處理上傳文件 .
構建 HTML 表單
讓我們開始構建一個包含兩個元素的簡單 HTML 表單: <input>
標籤允許用戶從本地計算機中選擇一個文件和一個 <button>
提交表單的標籤。這是它的樣子:
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit" role="button">Upload File</button>
</form>
使用 JavaScript 發送表單數據
現在,如果您單擊提交按鈕,表單將作為 action
發佈到自身 屬性未定義。我們要確保在提交表單時,使用 JavaScript XHR 對象將所選文件異步上傳到服務器(不刷新頁面)。
讓我們創建一個名為 upload.js
的新文件 並在您的 HTML 文件中添加對它的引用:
<script src="upload.js"></script>
接下來,定義兩個變量。您要發布表單數據的 URL,以及表單的 DOM 元素:
// define URL and for element
const url = "http://localhost:3000/upload-avatar";
const form = document.querySelector('form');
現在向表單添加一個事件監聽器來捕獲表單提交事件。另外,請確保阻止觸發默認操作:
// add event listener
form.addEventListener('submit', e => {
// disable default action
e.preventDefault();
// ....
});
接下來,創建一個新的 FormData 實例並將選定的文件添加到其中:
// collect files
const files = document.querySelector('[name=file]').files;
const formData = new FormData();
formData.append('avatar', files[0]);
// ....
最後,使用內置的 XHR 對象將數據 POST 到我們上面定義的 URL,並在控制台打印響應:
// post form data
const xhr = new XMLHttpRequest();
xhr.responseType = 'json';
// log response
xhr.onload = () => {
console.log(xhr.response);
};
// create and send the reqeust
xhr.open('POST', url);
xhr.send(formData);
這是完整的 upload.js
文件:
// define URL and for element
const url = "/upload-avatar";
const form = document.querySelector('form');
// add event listener
form.addEventListener('submit', e => {
// disable default action
e.preventDefault();
// collect files
const files = document.querySelector('[name=file]').files;
const formData = new FormData();
formData.append('avatar', files[0]);
// post form data
const xhr = new XMLHttpRequest();
// log response
xhr.onload = () => {
console.log(xhr.responseText);
};
// create and send the reqeust
xhr.open('POST', url);
xhr.send(formData);
});
Node.js API 返回的響應是一個 JSON 對象。現在,我們只是將響應打印到控制台。查看本指南,了解在 XHR 中處理 JSON 響應的幾種方法。
使用 Node.js 處理表單數據
對於通過 Node.js 和 Express 在服務器端處理文件上傳,我已經寫了一篇詳細的文章。我不會詳細介紹如何設置 Node.js 應用程序並安裝所有必需的包。請查看教程以了解所有這些內容。
本教程使用 express-fileupload 中間件處理 multipart/form-data
請求,提取文件(如果可用),並使其在 req.files
下可用 屬性。
你可以安裝express-fileupload
通過鍵入以下命令在您的項目中:
$ npm install express-fileupload --save
接下來,添加如下 Express 路由來處理並保存上述 JavaScript 代碼提交的文件:
app.post('/upload-avatar', async (req, res) => {
try {
if(!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
// use the name of the input field (i.e. "avatar")
// to retrieve the uploaded file
let avatar = req.files.avatar;
// use the mv() method to place the file in
// upload directory (i.e. "uploads")
avatar.mv('./uploads/' + avatar.name);
//send response
res.send({
status: true,
message: 'File is uploaded'
});
}
} catch (err) {
res.status(500).send(err);
}
});
以上是在 Node.js 應用程序中處理文件所需的最少代碼。
上傳多個文件
上面的示例說明瞭如何在 JavaScript 中上傳單個文件。如果你想上傳多個文件 立刻?不用擔心。通過一些改動,我們可以調整上面的代碼來支持多文件上傳。
首先,更新<input>
標籤允許用戶選擇多個文件:
<input type="file" name="file" multiple>
將表單提交 URL 更改為處理多個文件上傳的 URL:
const url = "http://localhost:3000/upload-photos";
接下來,更新 FormData
部分發送所有選定的文件,而不僅僅是一個:
Array.from(files).forEach(file => {
formData.append("photos", file);
});
最後,新建一個 Express 路由,接受多個文件並上傳到服務器:
app.post('/upload-photos', async (req, res) => {
try {
if (!req.files) {
res.send({
status: false,
message: 'No file uploaded'
});
} else {
let data = [];
//loop all files
_.forEach(_.keysIn(req.files.photos), (key) => {
let photo = req.files.photos[key];
//move photo to uploads directory
photo.mv('./uploads/' + photo.name);
});
//return response
res.send({
status: true,
message: 'Files are uploaded'
});
}
} catch (err) {
res.status(500).send(err);
}
});
恭喜!您現在可以一次上傳任意數量的文件。
結論
這就是所有人。在本教程中,您學習瞭如何使用 JavaScript 內置的 XMLHttpRequest
上傳文件 服務器端的對象和 Node.js。我們同時查看了單個文件上傳和多個文件上傳。
本文的目的是解釋在 JavaScript 和 Node.js 中成功上傳文件所需的基本步驟。對於在生產服務器上運行的真實應用程序,應該有一些驗證步驟。如果用戶選擇了錯誤的文件類型或文件大小超過了允許的限制,則應向用戶顯示錯誤。
XMLHttpRequest
還提供事件來跟踪文件下載和上傳進度。查看本指南以了解更多信息。
查看本指南,了解如何通過 Fetch API(XHR 的現代替代方案)處理文件上傳。