前言:

由于工作要求,需要写个文件上传的接口。之前接触的较少,都是使用现成的接口,自己写接口时却是遇到了难点。
该项目是在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后端保存文件的代码及流程基本完成。只是个人整理总结的内容,还请各位大佬指正。

Logo

前往低代码交流专区

更多推荐