JavaScript >> Javascript 文檔 >  >> Node.js

如何使用 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 的現代替代方案)處理文件上傳。


Tutorial JavaScript 教程
  1. 即將舉行的 WebdriverIO 研討會

  2. 通過 Capital One 開發者學院追求軟件職業

  3. 我已經用 simple-git-hooks 替換了 husky

  4. React 中的組件多態性

  5. 撲熱息痛.js💊| #69:解釋這段 JavaScript 代碼

  6. 使用 NodeJS 和 Terminus 優雅關閉

  7. 在 TypeScript 中使用 React Hooks 創建持久、同步的全局存儲

  1. 使用 useSelector()、@action、thunk 和 SSR 的無庫 React 存儲

  2. JavaScript 到 TypeScript | React 的完整指南⚛️

  3. 介紹 React-Scroll-To v2

  4. 如何在實施過程中減少債務

  5. 使用 Source Viewer 提高您的 jQuery 知識

  6. 如何使用 React Router 創建位置感知側邊欄

  7. 我注意到我所知道的每種語言的技能都非常有限

  1. JavaScript 面試問題 #44:JS 中的 Number 與 BigInt

  2. 最後一個該死的 Vue ToDo 應用程序

  3. 模態是承諾

  4. React 生態系統