NodeJS、Axios -将文件从本地服务器发送到另一台服务器

62o28rlo  于 2022-11-05  发布在  iOS
关注(0)|答案(7)|浏览(305)

我有一个API端点,可以让客户端将他们的csv发布到我们的服务器,然后再发布到其他服务器。我已经完成了将上传的文件保存到我们的服务器的服务器部分,但我无法完成其他部分。我一直收到错误{ message: 'File not found', code: 400 },这可能意味着文件从未到达服务器。我使用axios作为代理,有人知道如何完成这一点吗?谢谢。

// file = uploaded file
const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));
const request_config = {
    method: "post",
    url: url,
    headers: {
        "Authorization": "Bearer " + access_token,
        "Content-Type": "multipart/form-data"
    },
    data: form_data
};
return axios(request_config);

更新

正如axios文档所述,我尝试调用的API需要一个文件
//data是作为请求体发送的数据//只适用于请求方法'PUT'、'POST'和'PATCH' //当没有设置transformRequest时,必须是以下类型之一:// -字串、一般对象、数组缓冲区、数组缓冲区检视、URL搜寻参数// -仅限浏览器:表单数据、文件、Blob // -仅节点:流,缓冲区
有没有办法让axios发送一个完整的文件?谢谢。

ar5n3qh5

ar5n3qh51#

最早的两个答案对我不起作用。然而,这个答案起了作用:

const FormData = require('form-data'); // npm install --save form-data

const form = new FormData();
form.append('file', fs.createReadStream(file.path));

const request_config = {
  headers: {
    'Authorization': `Bearer ${access_token}`,
    ...form.getHeaders()
  }
};

return axios.post(url, form, request_config);

form.getHeaders()返回一个具有内容类型和边界的对象。
例如:

{ "content-type": "multipart/form-data; boundary=-------------------0123456789" }
yacmzcpb

yacmzcpb2#

我认为createReadStream是你的问题,因为它是异步的。试试这个。因为createReadStream扩展了事件发射器,我们可以“监听”它何时完成/结束。

var newFile = fs.createReadStream(file.path);

// personally I'd function out the inner body here and just call 
// to the function and pass in the newFile
newFile.on('end', function() {
  const form_data = new FormData();
  form_data.append("file", newFile, "filename.ext");
  const request_config = {
    method: "post",
    url: url,
    headers: {
        "Authorization": "Bearer " + access_token,
        "Content-Type": "multipart/form-data"
    },
    data: form_data
  };
  return axios(request_config);
});
zte4gxcn

zte4gxcn3#

这才是你真正需要的:

const form_data = new FormData();
form_data.append("file", fs.createReadStream(file.path));

const request_config = {
  headers: {
    "Authorization": "Bearer " + access_token,
    "Content-Type": "multipart/form-data"
  },
  data: form_data
};

return axios
  .post(url, form_data, request_config);
72qzrwbm

72qzrwbm4#

在我的例子中,fs.createReadStream(file.path)不起作用。
我不得不用缓冲液代替。

const form = new FormData();
form.append('file', fs.readFileSync(filePath), fileName);

const config = {
  headers: {
    Authorization: `Bearer ${auth.access_token}`,
    ...form.getHeaders(),
  },
};

axios.post(api, form.getBuffer(), config);
sbtkgmzw

sbtkgmzw5#

我已经做了一个拦截器,您可以连接到axios来处理node中的这种情况:axios-form-data。欢迎您提供任何反馈。

  • npm i axios-form-data
  • 例如:
import axiosFormData from 'axios-form-data';
import axios from 'axios';

// connect axiosFormData interceptor to axios
axios.interceptors.request.use(axiosFormData);

// send request with a file in it, it automatically becomes form-data
const response = await axios.request({
  method: 'POST',
  url: 'http://httpbin.org/post',
  data: {
    nonfile: 'Non-file value',
    // if there is at least one streamable value, the interceptor wraps the data into FormData
    file: createReadStream('somefile'),
  },
});

// response should show "files" with file content, "form" with other values
// and multipart/form-data with random boundary as request header
console.log(response.data);
z31licg0

z31licg06#

我也遇到了同样问题,我有一个“pdf-creator-service”,用于从html生成PDF文档。
我使用mustache模板引擎来创建HTML文档-https://www.npmjs.com/package/mustacheMustache.render函数将html作为字符串返回,我需要做些什么来将其传递给pdf-generator-service?因此,让我们看看下面我的建议

//...

async function getPdfDoc(props: {foo: string, bar: string}): Promise<Buffer> {
    const temlateFile = readFileSync(joinPath(process.cwd(), 'file.html'))

    mustache.render(temlateFile, props)
    const readableStream = this.getReadableStreamFromString(htmlString)

    const formData = new FormData() // from 'form-data'
    formData.append('file', options.file, { filename: options.fileName })
    const formHeaders = formData.getHeaders()

    return await axios.send<Buffer>(
      {
        method: 'POST',
        url: 'https://pdf-generator-service-url/pdf',
        data: formData,
        headers: {
          ...formHeaders,
        },
        responseType: 'arraybuffer', // ! important
      },
    )

}

getReadableStreamFromString(str: string): Readable {
    const bufferHtmlString = Buffer.from(str)
    const readableStream = new Readable() // from 'stream'

    readableStream._read = () => null // workaround error
    readableStream.push(bufferHtmlString)
    readableStream.push(null) // mark end of stream

    return readableStream
}
1qczuiv0

1qczuiv07#

适用于任何希望使用axios从本地文件系统(实际上是从任何具有正确流架构的地方)上传文件,并且不希望使用任何外部包(如form-data)的用户。

只需创建一个可读流并将其直接插入axios请求函数,如下所示:

await axios.put(
  url,
  fs.createReadStream(path_to_file)
)

Axios在节点上下文中接受Stream类型的数据参数。
至少在节点v.16.13.1和axios v.0.27.2中对我来说工作得很好

相关问题