代码之家  ›  专栏  ›  技术社区  ›  Eric

节点请求模块-发送表单数据时出错

  •  1
  • Eric  · 技术社区  · 8 年前

    我正在尝试从节点服务器向 api that expects a file and other form data as an multipart/form-data 是的。

    下面是我的代码

    var importResponse = function(csv){
      stringify(csv, function(err, output){
        request.post({
          headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
          url: url,
          formData: {
            surveyId: surveyId,
            file: {
                value: output,
                options: {
                    fileName: 'test.csv',
                    contentType:'text/csv'
                }
            }
          }
        }, function(error, response, body){
          console.log(body);
        });
      });
    }
    

    使用 request-debug 请求如下:

    request:
       { debugId: 1,
         uri: 'https://co1.qualtrics.com/API/v3/responseimports',
         method: 'POST',
         headers:
          { 'X-API-TOKEN': 'removed',
            'content-type':
             'multipart/form-data; boundary=--------------------------010815605562947295265820',
            host: 'co1.qualtrics.com',
            'content-length': 575 } } }
    

    以及回应:

    response:
       { debugId: 1,
         headers:
          { 'content-type': 'application/json',
            'content-length': '188',
            'x-edgeconnect-midmile-rtt': '28',
            'x-edgeconnect-origin-mex-latency': '56',
            date: 'Wed, 18 Jul 2018 03:57:59 GMT',
            connection: 'close',
            'set-cookie': [Array],
            'strict-transport-security': 'max-age=31536000; includeSubDomains; preload' },
         statusCode: 400,
         body:
          '{"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Missing Content-Type for file part. name=file","errorCode":"MFDP_3"},"requestId":"322a16db-97f4-49e5-bf10-2ecd7665972e"}}' } }
    

    我得到的错误是: Missing Content-Type for file part.

    我在选项中添加了这个:

    options: {
        fileName: 'test.csv',
        contentType:'text/csv'
    }
    

    当我查看请求时,似乎不包括表单数据。但也许那只是 请求调试 没有显示出来。

    我看到一个类似的 SO question 答案是 JSON.stringify 是的。 我尝试将代码更改为以下内容:

    request.post({
      headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
      url: url,
      body: JSON.stringify({
        surveyId: surveyId,
        file: {
            value: output,
            options: {
                fileName: 'test.csv',
                contentType:'text/csv'
            }
        }
      })
    

    但是,我得到了以下错误:

    {"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Missing boundary header"}}}
    

    我做错什么了?

    更新 当我试图在我的计算机上将文件值更改为csv时 fs.createReadStream('test.csv') ,效果很好

        file: {
            value: fs.createReadStream('test.csv'),
            options: {
                contentType: 'text/csv'
            }
        }
    

    所以我认为我给文件的方式有问题这个 output 我用作文件的变量看起来像 "QID1,QID2\nQID1,QID2\n1,2" 是的。我认为这是造成问题的原因,尽管这个错误有点误导人。我试着创造一个 Readable 我发现 StackOverFlow answer 就像这样:

    var s = new Readable
    s.push(output)
    s.push(null) 
    

    然而,这会导致 Unexpected end of input

    {"meta":{"httpStatus":"400 - Bad Request","error":{"errorMessage":"Unexpected end of input"}}}
    
    4 回复  |  直到 8 年前
        1
  •  2
  •   Mohammad Raheem    8 年前

    嘿Eric检查他们接受多部分请求的格式,就像我在驱动器上上传文件时所做的那样:

            request(options, function (err, response) {
                var boundary = '-------314159265358979323846';
                var delimiter = "\r\n--" + boundary + "\r\n";
                var close_delim = "\r\n--" + boundary + "--";
    
                var fileContent = 'Sample upload :)';
    
                var metadata = {
                    'name': 'myFile.txt',
                    'mimeType': 'text/plain\r\n\r\n'
                };
    
                var multipartRequestBody = delimiter + 'Content-Type: application/json\r\n\r\n' + JSON.stringify(metadata) + delimiter + 'Content-Type: ' + 'text/plain\r\n\r\n' + fileContent + close_delim;
    
                request(options, function (err, response) {
                    var url = 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&access_token=' + JSON.parse(response.body).access_token;
                    var options = {
                        method: 'POST',
                        url: url,
                        headers: {
                            'Content-Type': 'multipart/related; boundary="' + boundary + '"'
                        },
                        body: multipartRequestBody
                    };
    
                    request(options, function (err, response) {
                        res.send({resultdata: response.body});
                    });
                });
            });
    

    根据端点接受设置多部分。

        2
  •  1
  •   Anthony Morris    8 年前

    您是否可能对文件使用了不正确的属性名?

    快速阅读 request 节点模块使我认为您应该使用 custom_file 而不是 file 是的。

    您可以在这里阅读更多信息: https://github.com/request/request#forms

        3
  •  1
  •   Eric    8 年前

    我发现了问题我的第一个解决方案很好,但是 fileName 应该是的 filename

    var importResponse = function(csv){
      stringify(csv, function(err, output){
        request.post({
          headers: {'X-API-TOKEN':token, 'content-type' : 'multipart/form-data'},
          url: url,
          formData: {
            surveyId: surveyId,
            file: {
                value: output,
                options: {
                    filename: 'test.csv', //filename NOT fileName
                    contentType:'text/csv'
                }
            }
          }
        }, function(error, response, body){
          console.log(body);
        });
      });
    }
    
        4
  •  0
  •   Sachin S    8 年前

    使用express之类的框架(它们自动解析头和响应)和multer之类的npm模块来处理多部分表单数据有助于它们为您完成所有繁重的工作。