node中間層實現檔案上傳

憐白發表於2018-06-10

  一般情況下,前端的檔案上傳一般都是通過form表單的(<input type=”file” />)來完成檔案的上傳,如果使用node中間層完成跨域,檔案的上傳就需要在node中間層處理成可讀流,轉成formData完成轉發。

 

一、form表單檔案上傳

  這是最常見的檔案上傳方式,通過form表單實現,簡單實用,設定一下method、enctype、action屬性就可以了,多檔案上傳需要設定multiple屬性(部分瀏覽器支援還是有些問題的)。

1 <form method="post" enctype="multipart/form-data" action="/api/upload">
2     <input type="text" name="username">
3     <input type="password" name="password">
4     <input type="file" name="file">
5     <input type="submit">
6 </form>

 

二、FormData實現檔案上傳

  FormData物件用以將資料編譯成鍵值對,以便向後臺傳送資料。其主要用於傳送表單資料,但亦可用於傳送帶鍵資料(keyed data),而獨立於表單使用。對部分瀏覽器對multiple屬性不支援的情況,可以使用formData的提交方式完成。

1 <!-- 獲取上傳檔案轉成formData型別的檔案 -->
2 <input multiple id="file" name="file" type="file" />
3 <button id="btn">提交</button>
 1 const oFile = document.getElementById(`file`)
 2 const oBtn = document.getElementById(`btn`)
 3 
 4 oBtn.addEventListener(`click`, () => {
 5     files = oFile.files
 6     const formData = new FormData()
 7     formData.append(`file`, files[0])
 8     formData.append(`file1`, files[1])
 9 
10     fetch(`/api/upload`, {
11         method: "POST",
12         body: formData
13     })
14 })
  • 使用fetch請求不要設定Content-Type,否則無法請求
  • fetch請求預設是不帶cookie

 

三、node中間層完成檔案上傳跨域

  跨域是因為瀏覽器的同源策略造成,跨域的方法有很多中,這裡使用的是node中間層代理完成(服務端之間的請求是不存在跨域問題)。

  node無法直接解析上傳的檔案,需要引入擴充包connect-multiparty完成,這樣就可以拿到檔案資料。

  拿到上傳檔案,需要在node中轉發請求後臺server,這裡的檔案不能直接發給後臺,需要將上傳的檔案使用fs.createReadStream轉成可讀流,同時引入 form-data 包(node環境是沒有formData物件的),這樣就可以實現node中間層轉發檔案型別

  node部分程式碼:

 1 const fs = require(`fs`)
 2 const path = require(`path`)
 3 const FormData = require(`form-data`)
 4 const express = require(`express`)
 5 const fetch = require(`node-fetch`)
 6 const router = express.Router()
 7 const multipart = require(`connect-multiparty`);
 8 var multipartMiddleware = multipart()
 9 
10 router.post(`/upload`, multipartMiddleware, function (req, res) {
11     // console.log(req.body, req.files);
12 
13     const { path: filePath, originalFilename } = req.files.file
14     const newPath = path.join(path.dirname(filePath), originalFilename)
15 
16     fs.rename(filePath, newPath, function (err) {
17         if (err) {
18             return;
19         }
20         else {
21             const file = fs.createReadStream(newPath)
22             const form = new FormData()
23             form.append(`file`, file)
24 
25             fetch(`http://localhost:8080/upload`, {
26                 method: "POST",
27                 body: form
28             })
29         }
30     })
31     res.json({})
32 });
33 
34 module.exports = router; 

 

注意:

  • node無法直接解析上傳檔案,需要引入npm包connect-multiparty中介軟體,或者引入npm包multiparty
  • node拿到檔案,需要使用fs.createReadStream轉成可讀流
  • node環境沒有formData物件,需要引入npm包form-data
  • fetch請求提交formData資料,不能設定Comtemt-Type

  

  完整的程式碼請參考 node中間層實現檔案上傳

 

  如果喜歡請關注我的Github,給個Star吧,我會定期分享一些JS中的知識,^_^

相關文章