1. 程式人生 > >node上傳檔案到服務端

node上傳檔案到服務端

前言:

由於工作要求,需要寫個檔案上傳的介面。之前接觸的較少,都是使用現成的介面,自己寫介面時卻是遇到了難點。
該專案是在vue、koa基礎上搭建的,關於路由及其他相關知識,可檢視其他文章。
現將自己的理解寫下了,方便日後差異。如有不當地方,還請指正。

前端:

html

html結構可以寫的很簡單,一個input標籤就足夠。程式碼如下:
<input type="file" id="upload__input" @change="uploadFile" accept="" multiple>

js:

js主要處理input檔案變化後請求介面,並傳引數。
需要注意的是,引數不像表單那樣符合鍵值對的要求,需要使用formData的格式傳遞。程式碼如下:

	uploadFile (e) {
        var fileValue = document.querySelector('#el-upload__input')
        this.srcOthers = fileValue.files[0];
        var formData = new FormData();
        formData.append('file', this.srcOthers);

        this.$http.post(this.rootUrl + "postsTxtFile/",formData)
          .then((data) => {
            console.log(data)
          })
          .catch((err) => {
            console.log(err, 'error');
          });
      }

程式碼中核心是宣告formData變數,將input的files變數傳遞進去。可以模擬表單的形式形成鍵值對,用於非同步上傳二進位制檔案。

後端:

後端在拿到引數後,引數形式如下:

{
    "method": "POST", 
    "url": "/api/postsTxtFile/", 
    "header": {
        "accept-language": "zh-CN,zh;q=0.9", 
        "accept-encoding": "gzip, deflate, br", 
        "referer": "http://localhost:8080/pageCompare", 
        "content-type": "multipart/form-data; boundary=----WebKitFormBoundaryKdkJ1bBxZAeKZ1sS", 
        "user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6726.400 QQBrowser/10.2.2265.400", 
        "origin": "http://localhost:8080", 
        "accept": "application/json, text/plain, */*", 
        "content-length": "7140", 
        "connection": "close", 
        "host": "localhost:4000"
    }
}

引數中並無法取到二進位制檔案的內容,因此需要將傳遞的引數解析為指定形式。在此,需要介紹使用中介軟體進行傳遞引數的解析。
因為傳遞的檔案型別為multipart/form-data型別,可使用connect-multiparty等中介軟體進行轉換,本專案中使用的是koa-body進行資料格式的轉換。

Koa-body

安裝

$ npm install koa-body

使用

如官網所示:
koa-body官網例項

示例中index.js中引入koa之後,使用app.use的方式使用。如下:

const koa = require('koa');
const koaBody = require('koa-body');

// 中介軟體
app.use(koaBody({
    jsonLimit: '20mb',
    multipart: true
}));

程式碼中KoaBody函式傳遞了兩個引數,用於限制json的大小以及設定引數的型別為multipart型別。

另一種呼叫方式是在介面的router時使用,例如:

import Router from 'koa-router';
import koaBody from 'koa-body';

import postsTxtFile from '../application/postsTxtFile'
export default function () {
  const router = Router();
  router.prefix('/api');
  router.post('/postsTxtFile/', koaBody(
    {
      jsonLimit: '20mb',
      multipart: true
    }
  ),
    async (ctx) => {
      // => POST body
      ctx.body = await postsTxtFile(ctx.request);
    // let para = ctx.request;
    // let res = await postsTxtFile(para);
    // ctx.body = res;
  });
  return router.routes();
}

程式碼中,在宣告postsTxtFile介面時,呼叫KoaBody函式,限制了json資料大小以及資料型別為multipart。而後呼叫postsTxtFile函式,返回處理後的資訊。
KoaBody處理後的請求files欄位格式如下:

"para": {
        "file": {
            "size": 287, 
            "path": "C:\\Users\\guojiangwei\\AppData\\Local\\Temp\\upload_30e4bc4b5cd52550160803d9f2f77904", 
            "name": "報告解讀靜態頁面.txt", 
            "type": "text/plain", 
            "mtime": "2018-11-27T07:57:56.510Z"
        }
    }

postsTxtFile.js

處理請求的介面函式的程式碼如下:

import fs from 'fs';
async function main(para) {
  let res = {};
  if (para && para.files) {
    // res = {
    //   data: para.files.file.name
    // }
    // 獲得檔名
    var filename = para.files.file.name;

    // 複製檔案到指定路徑
    var targetPath = 'src/uploadText/' + filename;

    // 複製檔案流
    fs.createReadStream(para.files.file.path).pipe(fs.createWriteStream(targetPath));

    // 響應ajax請求,告訴它檔案上傳成功
    res = { code: 200, data: { result: 'success' } };
    return res;
  } else {
    return {
      code: -1,
      result: 'no files'
    };
  }
}
export default main;

程式碼中獲取了請求中的files的內容,並儲存到指定目錄中。

至此由前端上傳檔案到node後端儲存檔案的程式碼及流程基本完成。只是個人整理總結的內容,還請各位大佬指正。