【问题标题】:Sending the POST request from node.js server with *.zip/*.wgt file to the Wookie Server使用 *.zip/*.wgt 文件从 node.js 服务器发送 POST 请求到 Wookie 服务器
【发布时间】:2013-02-24 08:54:55
【问题描述】:

我尝试将带有 POST 请求的 *.wgt 文件(有效的 *.zip 文件)从 node.js 发送到运行 Wookie Server 的其他服务器。我已经关注了 http 服务器fs 的 node.js 文档以及 stackoverflow 上的另外两个帖子(Node.js POST File to Serverhow to upload a file from node.js),但我没有设法让它工作.

我已经做了什么:

我有存储在 node.js 服务器上的 *.wgt 文件。我在节点中创建一个 http 服务器,准备对 Wookie REST API 的 POST 请求,使用 fs.createReadStream() 获取 *.zip 文件流,然后使用 pipe() 流式传输它。但我得到以下错误响应:

错误:找不到上传到服务器的文件。发送的请求 客户端在语法上不正确(没有文件上传到服务器)。

此特定请求的 Wookie Server API 参考如下所示:

POST {wookie}/widgets {file} - 向服务器添加一个小部件。该方法在响应中回显小部件元数据。

我的代码如下:

var http = require('http');
var fs = require('fs');
var file_name = 'test.wgt';

// auth data for access to the wookie server api
var username = 'java';
var password = 'java';
var auth = 'Basic ' + new Buffer(username + ':' + password).toString('base64');     

// boundary key for post request            
var boundaryKey = Math.random().toString(16);
var wookieResponse = "";

// take content length of the request body: see https://stackoverflow.com/questions/9943010/node-js-post-file-to-server
var body_before_file = 
      '--' + boundaryKey + '\r\n'
      + 'Content-Type: application/octet-stream\r\n' 
      + 'Content-Disposition: form-data; name="file"; filename="'+file_name+'"\r\n'
      + 'Content-Transfer-Encoding: binary\r\n\r\n';
var body_after_file = "--"+boundaryKey+"--\r\n\r\n";

fs.stat('./uploads/'+file_name, function(err, file_info) {
    console.log(Buffer.byteLength(body_before_file) +"+"+ file_info.size +"+"+ Buffer.byteLength(body_after_file));

    var content_length = Buffer.byteLength(body_before_file) + 
        file_info.size +
        Buffer.byteLength(body_after_file);

    // set content length and other values to the header
    var header = {
        'Authorization': auth,
        'Content-Length': String(content_length),
        'Accept': '*/*',
        'Content-Type': 'multipart/form-data; boundary="--'+boundaryKey+'"',//,
        'Accept-Encoding': 'gzip,deflate,sdch',
        'Accept-Charset': 'ISO-8859-2,utf-8;q=0.7,*;q=0.3'
    };
    // set request options
    var options = {
            host: appOptions.hostWP,
            port: 8080,
            path: '/wookie/widgets',
            method: 'POST',
            headers: header
    };

    // create http request
    var requ = http.request(options, function(res) {
        res.setEncoding('utf8');    
        res.on('data', function (chunk) {
            wookieResponse = wookieResponse + chunk;
        });
        res.on('end', function (chunk) {
            wookieResponse = wookieResponse + chunk;
            console.log(wookieResponse);
        })
    });

    // write body_before_file (see above) to the body request
    requ.write(body_before_file);

    // prepare createReadStream and pipe it to the request
    var fileStream = fs.createReadStream('./uploads/'+file_name);
    fileStream.pipe(requ, {end: false});

    // finish request with boundaryKey
    fileStream.on('end', function() {
        requ.end('--' + boundaryKey + '--\r\n\r\n');
    });

    requ.on('error', function(e) {
        console.log('problem with request: ' + e.message);
    });
});

我做错了什么以及如何通过来自 node.js 的 POST 请求实现正确的 *.wgt/*.zip 文件上传?

干杯, 迈克尔

【问题讨论】:

    标签: node.js post widget zip http-post


    【解决方案1】:

    我实现了所描述的目标:将带有 *.zip/*.wgt 文件的 node.js 的 POST 请求发送到另一台服务器。

    我没有使用问题中介绍的方法来解决这个问题:使用请求模块逐步构建请求。我做了一些研究,发现了有趣的 node.js 模块:form-data。这个模块有什么作用? Readme.md 说:

    创建可读的“multipart/form-data”流的模块。可以使用 提交表单和文件上传到其他网络应用程序。

    在列出的示例中,我找到了以下示例:

    var CRLF = '\r\n';
    var form = new FormData();
    
    var options = {
      header: CRLF + '--' + form.getBoundary() + CRLF + 'X-Custom-Header: 123' + CRLF + CRLF,
      knownLength: 1
    };
    
    form.append('my_buffer', buffer, options);
    
    form.submit('http://example.com/', function(err, res) {
      if (err) throw err;
      console.log('Done');
    });
    

    在上面的示例中,创建了一个FormData() 对象,将数据附加到表单,然后提交表单。此外,还创建了一个自定义 hedear。

    我将我提出的代码与上述示例中的代码合并,得到了解决我的问题的代码:

    var formData = require('form-data');
    var fs = require('fs');
    
    var CRLF = '\r\n';
    var form = new FormData();
    
    var options = {
        header: '--' + form.getBoundary() +
                CRLF + 'Content-Disposition: form-data; name="file";'+  
                        'filename="bubbles.wgt"'+
                CRLF + 'Content-Type: application/octet-stream' +
                CRLF + CRLF
        };
    
    form.append('file',fs.readFileSync('./uploads/bubbles.wgt'),options);
    
    form.submit({
            host: host,
            port: '8080',
            path: '/wookie/widgets',
            auth: 'java:java'
            }, function(err, res) {
                if (err) throw err;
                console.log('Done');
                console.log(res);
            });
    

    希望对其他人有所帮助。

    干杯, 迈克尔

    【讨论】:

      猜你喜欢
      • 2012-04-03
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多