如何在KOA中解析二进制数据(“multipart/form-data”)?

问题描述 投票:0回答:1

如果我发送带有文本选项的 POST 查询,一切正常:

query from front-end:

const request = require("request")
const options = {
 method: 'POST',
 url: 'http://localhost:4000/user',
 headers:    form: { data: '12345' }
 }

在服务器端(KOA)我可以获取 a.m.query 的解析数据:

ctx.request.method: "POST"
ctx.request.originalUrl: "user"
ctx.request.body.data: "12345"

但是如果我发送带有二进制数据(文件)的 POST 查询:

const fs = require("fs");
const request = require("request");
const options = { method: 'POST',
  url: 'http://localhost:4000/user',
  headers: 
   {
     'content-type': 'multipart/form-data},
  formData: 
   { '': 
      { value: 'fs.createReadStream("F:\\image.jpg")',
        options: 
         { filename: 'F:\\image.jpg',
           contentType: null }
 } } };

我不知道,如何在服务器部分(KOA)上访问此二进制数据(“image.jpg),在 ctx.request 中有任何包含此数据的字段...

koa
1个回答
1
投票

您可以使用

busboy
来实现此目的。 我为此写了一个要点,但我将把它和一些评论一起嵌入这里。

让我们创建一个助手,以一种承诺友好的方式解析文件。

// parse.js
import Busboy from 'busboy'

/**
 * Parses a single file from a Node request.
 *
 * @param  {http.IncommingRequest} req
 * @return {Promise<{ file: Stream, filename: string>}
 */
export default function parse (req) {
  return new Promise((resolve, reject) => {
    const busboy = new Busboy({
      headers: req.headers,
      limits: {
        files: 1 // allow only a single upload at a time.
      }
    })

    busboy.once('file', _onFile)
    busboy.once('error', _onError)
    req.pipe(busboy)

    function _cleanup () {
      busboy.removeListener('file', _onFile)
      busboy.removeListener('error', _onError)
    }

    function _onFile (fieldname, file, filename) {
      _cleanup()
      resolve({ file, filename })
    }

    function _onError (err) {
      _cleanup()
      reject(err)
    }
  })
}

现在我们需要使用它。假设您要上传到 AWS S3。

import Koa from 'koa'
import parse from './busboy'
import AWS from 'aws-sdk'

const app = new Koa()

const s3 = new AWS.S3({ 
  params: { Bucket: 'myBucket' } 
})

// Assuming this is a route handler.
app.use(async (ctx) => {
  const { file, filename } = await parse(ctx.req)
  // `file` is a Stream. Pass this to S3, Azure Blob Storage or whatever you want.
  // `filename` is the file name specified by the client.
  const result = await s3.upload({
    Key: filename,
    Body: file
  }).promise()

  ctx.body = result
})

为了简洁起见,这是在客户端上使用

axios
上传文件的方法。

// `file` is a DOM File object.
function upload (file) {
  const data = new window.FormData()
  data.append('file', file, file.name)
  return axios.post('/upload', data)
}
© www.soinside.com 2019 - 2024. All rights reserved.