简体   繁体   English

使用 FormData 多部分发布请求在节点 js 中上传文件

[英]Upload file in node js with FormData multipart post request

I don't understand what is wrong with this use case.我不明白这个用例有什么问题。 If the body of the requested file is passed to form-data directly http upload doesn't work but if write to file and then pass file stream reader to form-data request works.如果请求文件的正文直接传递给表单数据 http 上传不起作用,但如果写入文件然后将文件 stream 读取器传递给表单数据请求工作。

Test client测试客户端

import fs from "fs";
import FormData from "form-data";
import ky from "ky-universal";

const main = async () => {
  const { body } = await ky.get(
    "https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf"
  );

  const form = new FormData();

  // This works
  const writeStream = fs.createWriteStream("./tmp.pdf");
  body.pipe(writeStream);
  const fileStream = fs.createReadStream("./tmp.pdf");
  form.append("file", fileStream);

  // This doesn't work
  // form.append("file", body);

  form.append("param", "param value");

  const res = await ky.post(`http://localhost:3030/upload`, {
    timeout: 20000,
    body: form,
  });

  const json = await res.json();
  console.log(json);
};

Test server测试服务器

// mkdir uploads
// npm install express multer
import express from "express";
import multer from "multer";

var upload = multer({ dest: "uploads/" });

var app = express();

app.post(
  "/upload",
  upload.single("file"),
  function (req, res, next) {
    console.dir(req.file);
    console.dir(req.body);
    res.json({ ok: true });
  }
);

app.listen(process.env.PORT || 3030);

https://gist.github.com/davidnussio/8148b2296a476637bb7e4dae8cf52d44 https://gist.github.com/davidnussio/8148b2296a476637bb7e4dae8cf52d44

UPDATE更新

Workaround解决方法

Maybe related with this issue and maybe related to me working with node PassThrough streams but as workaround, instead to plug response directly to form-data to the post request i consume the stream to new buffer variable.可能与此问题有关,也可能与我使用节点 PassThrough 流有关,但作为解决方法,将表单数据的响应直接插入到发布请求中,我将 stream 用于新的缓冲区变量。

async function client() {
  const { body } = await ky.get(
    "https://file-examples-com.github.io/uploads/2017/10/file-sample_150kB.pdf"
  );

  return new Promise((resolve, reject) => {
    const data = [];
    const writableStream = new stream.Writable({
      defaultEncoding: "utf-8",
    });

    writableStream._write = (chunk, encoding, next) => {
      data.push(Buffer.from(chunk, encoding));
      next();
    };

    stream.pipeline(body, writableStream, (err) => {
      if (err) {
        return reject(err);
      }
      const form = new FormData();

      const buffer = Buffer.concat(data);

      form.append("file", buffer, { filename: 'tmp.pdf' });
      form.append("param", "param-value");

      ky.post(url1, {
        timeout: 20000,
        body: form,
      })
        .json()
        .then((json) => resolve(json))
        .catch((error) => reject(error.message));
    });
  });
}

To upload a file you need to send the correct content-type in the header ( "multipart/form-data").要上传文件,您需要在 header(“multipart/form-data”)中发送正确的内容类型。 The FormData prepares the header for you and you can obtain this header through form.getHeaders(). FormData为你准备了header,你可以通过form.getHeaders()获取这个header。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM