【问题标题】:NodeJS, Axios - post file from local server to another serverNodeJS,Axios - 将文件从本地服务器发布到另一台服务器
【发布时间】:2018-10-29 04:48:24
【问题描述】:

我有一个 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 时,必须是以下类型之一: // - 字符串、普通对象、ArrayBuffer、ArrayBufferView、URLSearchParams // - 仅限浏览器:FormData、File、Blob // - 仅节点:流、缓冲区

有没有办法让axios整体发送文件?谢谢。

【问题讨论】:

    标签: node.js axios multipartform-data


    【解决方案1】:

    2 个最旧的答案对我不起作用。然而,这成功了:

    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" }
    

    【讨论】:

    • 这很有帮助。非常感谢!这是另一个有用的示例,展示了如何在不使用文件系统的情况下模拟文件上传:github.com/axios/axios/issues/1006#issuecomment-320165427
    • 像魅力一样工作。这很有帮助。以上解决方案均无效。
    • 嗨!感谢您的回答!在打字稿中,我收到一个错误:“ReadStream”类型的参数不可分配给“字符串”类型的参数 |斑点'。 “ReadStream”类型缺少“Blob”类型的以下属性:大小、类型、arrayBuffer、切片和另外 2 个。有什么想法吗?
    【解决方案2】:

    我认为 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);
    });
    

    【讨论】:

    • 嗨詹姆斯。您的解决方案确实有效。但是,createReadStream 是否将整个文件读入内存,如果是,我可能会遇到大量文件的内存问题。
    • 因此,使用 Request 模块(导入它),您可以像这样轻松地做到这一点: newFile.pipe(request(request_config)) 。我认为 axios 也可以做到。但想法是,在文件中流式传输,并将其通过管道传输到 request/axios 以进行传输。
    • @jamesemanon 你有任何代码 sn-p 来管道文件流以供 axios 上传吗?如果是,请在此处发布
    • 如果要上传多个文件怎么办? @jamesemanon
    • 嗨!感谢您的回答!在打字稿中我收到一个错误:Argument of type 'ReadStream' is not assignable to parameter of type 'string | Blob'. Type 'ReadStream' is missing the following properties from type 'Blob': size, type, arrayBuffer, slice, and 2 more. 有什么想法吗?
    【解决方案3】:

    这是你真正需要的:

    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);
    

    【讨论】:

      【解决方案4】:

      就我而言, 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);
      
      

      【讨论】:

        【解决方案5】:

        我已经做了一个拦截器,你可以连接到 axios 来处理节点中的这种情况: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);
        

        【讨论】:

          猜你喜欢
          • 2022-11-23
          • 2019-01-24
          • 2015-08-01
          • 2016-10-18
          • 2011-11-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多