node.js - request 上传文件错误
伊谢尔伦
伊谢尔伦 2017-04-17 13:06:41
0
2
903

我使用 multiparty 解析前端上传的文件,然后使用 request 上传到文件服务器。

form.on('part', function(part) {

    if (part.filename) {

        var formData = {
            name: part.filename,
            my_file: part
        };

        request.post({
            url: 'http://service.com/upload',
            formData: formData
        }, function optionalCallback(err, httpResponse, body) {
            if (err) {
                return console.error('upload failed:', err);
            }
            console.log('Upload successful! Server responded with:', body);
        });

    }

});

request的官方示例是将文件的 readStream , 传入 formdata。例如

var formData = {
    my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
}

但是我并不想先创建临时文件,然后再获取 readStream。 由于 multiparty的 part 也是一种可读流, transform stream,它同时具有 readStream 和 writeStream 的接口,所以我想将 part 直接传入formdata。 但是遇到了下面的错误

TypeError: form-data: Invalid non-string/buffer chunk

由于文件服务器是远端的线上服务器,它的细节我并不清楚。 但是它确实能支持从文件创建的 readStream 的 formdata 的上传。 但是 part 就不行。

这里想请教一下, transform stream 和 fs.createStream 有什么不同? 有什么办法可以将 transform stream 的数据 转交给 readStream? 谢谢。

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

reply all(2)
Peter_Zhu

Well, I found the answer myself.
Use form-data

Use form-data

The part mentioned in the question is a transform flow. This flow is generally used to transform, that is, to transform data. It can be both read and written. In fact, it will only output when there is data input. Think of it as a box that transforms data.

The requset module can post form data, like this.

var form = {
            name: 'xxx',
            my_file: streamObj
        };

        request.post({
            url: 'http://service.com/upload',
            formData: form
        },callback);

This form is just a simple js object, and request will convert it into formdata.
request can get all the information it needs from streamObj, but this stream only supports fs.readStream, http.response. For other streams, file-related information needs to be provided.

The following is the original text, which roughly means what is said above.

Form-Data can recognize and fetch all the required information from common types of streams (fs.readStream, http.response and mikeal's request), for some other types of streams you'd need to provide "file" -related information manually:

So, the form must be constructed in the following way, the original form-data. Of course, first you have to npm install form-data.

var form = new FormData();
 
  form.append('fieldname', part, {
    filename: part.filename,
    contentType: part.headers['content-type'],
    knownLength: part.byteCount
  });

filename, headers, and byteCount are all part’s own properties.

Set http header Transfer-Encoding: chunked

When the part event is triggered, it means that the file part in the client form begins to upload to the current server. At this time, we will hand over the part to send the data to File server’s http request. At this time, a header

must be specified for this request.
Transfer-Encoding: chunked

Why is this? Because the content-length is uncertain at this time, because the client data has not been uploaded yet. We must inform the file server that the length of the request is not yet determined, and you must wait until I tell you to stop .

This is the meaning of setting this header.

小葫芦

Try using pipe?

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template