• Node.js Video Tutorials

Node.js - 上傳檔案



在許多 Web 應用程式中,客戶端機器上的使用者需要將檔案(例如使用者使用 Facebook 或 Instagram 應用程式上傳影像和影片)上傳到伺服器。NPM 登錄檔上提供了許多開源模組,可以使用這些模組在 Node.js 應用程式中啟用上傳檔案的功能。formidable 模組提供了一個方便的 API 來處理檔案上傳。formidable 模組可以匯入到核心 Node.js 模組中,以及內建的 http 模組和 Express 應用程式中。

Formidable

Formidable 模組是一個快速且流式處理的多部分解析器,能夠自動將檔案上傳寫入磁碟。它佔用記憶體少,並且具有高效的錯誤處理機制。

第一步,使用以下命令安裝 formidable 模組:

npm install formidable

在本節中,下面顯示了在包含 http 模組的 Node.js 應用程式和 ExpressJs 應用程式中使用 Formidable 模組的示例用法:

使用 Node.js http 模組

以下示例呼叫 createServer() 函式啟動 Node.JS 伺服器,並呈現一個多部分 HTML 表單,供使用者選擇要上傳的檔案。

提交檔案後,表單資料將被解析,並且上傳的檔案將複製到磁碟上的預設位置。

var http = require('http');
var formidable = require('formidable');

var errors = formidable.formidableErrors;

const server = http.createServer(async (req, res) => {
   if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
      // parse a file upload
      const form = new formidable.IncomingForm();
      let fields;
      let files;
      try {
         [fields, files] = await form.parse(req);
      } catch (err) {

         res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
         res.end(String(err));
         return;
      }
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ fields, files }, null, 2));
      return;
   }

   // show a file upload form
   res.writeHead(200, { 'Content-Type': 'text/html' });
   res.end(`
      <h2>With Node.js <code>"http"</code> module</h2>
      <form action="/api/upload" enctype="multipart/form-data" method="post">
      <div>Text field title: <input type="text" name="title" /></div>
      <div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
      <input type="submit" value="Upload" />
      </form>
   `);
});
server.listen(5000, () => {
   console.log('Server listening on https://:5000/ ...');
});

執行應用程式後,瀏覽器將顯示以下表單以選擇要上傳的檔案。

Nodejs http Module

上傳操作成功後,瀏覽器將顯示以下結果:

{
  "fields": {
      "title": [
         "test"
      ]
   },
   "files": {
      "multipleFiles": [
         {
            "size": 4203211,
            "filepath": "C:\\Users\\user\\AppData\\Local\\Temp\\930f2f754006b790729e0d200",
            "newFilename": "930f2f754006b790729e0d200",
            "mimetype": "image/png",
            "mtime": "2023-12-24T08:04:09.856Z",
            "originalFilename": "1.png"
         }
      ]
   }
}

使用 Express.js

在 Express.JS 程式碼中使用 formidable 模組的最簡單用法如下:

import express from 'express';
import formidable from 'formidable';

const app = express();

app.get('/', (req, res) => {
   res.send(`
      <h2>With <code>"express"</code> npm package</h2>
      <form action="/api/upload" enctype="multipart/form-data" method="post">
      <div>Text field title: <input type="text" name="title" /></div>
      <div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
      <input type="submit" value="Upload" />
      </form>
   `);
});
app.post('/api/upload', (req, res, next) => {
   const form = formidable({});

   form.parse(req, (err, fields, files) => {
      if (err) {
         next(err);
         return;
      }
      res.json({ fields, files });
   });
});

app.listen(5000, () => {
   console.log('Server listening on https://:5000 ...');
});

您還可以安裝並使用 body-parser 模組來解析上傳過程中多部分 HTML 表單資料。

Multer

另一個能夠處理檔案上傳的有用 NPM 模組稱為 Multer。使用者可以一次上傳一個或多個檔案。

要安裝,請使用以下命令:

npm install multer

在 Express 應用程式的開頭,包含 Multer 並宣告 Multer 物件。

const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })

假設您有一個路由來處理 GET 請求並顯示一個將表單釋出到 /upload 路由的多部分 HTML 表單,請新增以下函式來處理 POST 請求:

app.post("/upload", upload.single("myFile"), (req, res) => {
   console.log("Body: ", req.body);
   console.log("File: ", req.file);
   res.send("File successfully uploaded.");
});

要將上傳的檔案儲存在指定位置而不是臨時檔案的預設位置,請配置 Multer 位置如下:

var storage = multer.diskStorage({   
   destination: function(req, file, cb) { 
      // destination is used to specify the path of the directory in which the files have to be stored
      cb(null, './uploads');    
   }, 
   filename: function (req, file, cb) { 
      // It is the filename that is given to the saved file.
      cb(null , file.originalname);   
   }
});

// Configure storage engine instead of dest object.
const upload = multer({ storage: storage })
廣告