1

busboy を使用してリクエストを受け取り、アップロードのためにファイルを Imgur にパイプする node.js サーバーを作成しました。ただし、「ファイルのアップロードが速すぎます!」というメッセージが表示され続けます。Imgur からの応答であり、何が問題なのか正確にはわかりません。busboy に関するコード スニペットは次のとおりです。

var express = require('express');
var Busboy = require('busboy');
var fs = require('fs');
var request = require('request-promise');
var router = express.Router();

router.post('/u', function(req, res, next) {
    var busboy = new Busboy({headers: req.headers});
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        if(fieldname == 'image') {
            var options = {
                uri: 'https://api.imgur.com/3/image',
                method: 'POST',
                headers: {
                    'Authorization': 'Client-ID ' + clientID // put client id here
                },

                form: {
                    image: file,
                    type: 'file'
                }
            };

            request(options)
                .then(function(parsedBody) {
                    console.log(parsedBody);
                })
                .catch(function(err) {
                    console.log(err);
                });
        }
    });
    busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
        console.log('field');
    });
    busboy.on('finish', function() {
        res.status(200).end();
    });
    req.pipe(busboy);
});

ご覧のとおり、リクエスト ファイルを imgur のリクエストに直接パイプしています。ファイルをディスクに保存してから使用するだけで ReadStream を提供すると、fs.createReadStream()完全に機能するため、リクエストからリクエストに直接パイプしようとするとエラーが発生する理由がよくわかりません。Imgurから得た正確な応答は次のとおりです。

StatusCodeError: 400 - {"data":{"error":"Uploading file too fast!","request":"\/3\/image","method":"POST"},"success":false,"status":400} 

誰かが以前にこれに遭遇した場合、それは役に立ちます...

4

1 に答える 1

3

最初の問題は、ファイルのアップロードに form ではなく formData を使用する必要があることです。そうしないと、リクエスト ライブラリは正しい HTTP リクエストを送信しません。

2 つ目の問題は、ストリーム オブジェクトが完全に処理されるまで、コンテンツの長さが正しくないことです。データを自分でバッファリングし、busboy からの最初のファイル ストリームが処理された後に渡すことができます。*

これにより、次のようなものが得られます

var express = require('express');
var Busboy = require('busboy');
var fs = require('fs');
var request = require('request-promise');
var router = express.Router();

router.post('/u', function(req, res, next) {
    var busboy = new Busboy({headers: req.headers});
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        if(fieldname == 'image') {
            // the buffer
            file.fileRead = [];
            file.on('data', function(data) {
                // add to the buffer as data comes in
                this.fileRead.push(data);
            });

            file.on('end', function() {
                // create a new stream with our buffered data
                var finalBuffer = Buffer.concat(this.fileRead);

                var options = {
                    uri: 'https://api.imgur.com/3/image',
                    method: 'POST',
                    headers: {
                        'Authorization': 'Client-ID ' + clientID // put client id here
                    },

                    formData: {
                        image: finalBuffer,
                        type: 'file'
                    }
                };

                request(options)
                    .then(function(parsedBody) {
                        console.log(parsedBody);
                    })
                    .catch(function(err) {
                        console.log(err);
                    });
            });
        }
    });
    busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
        console.log('field');
    });
    busboy.on('finish', function() {
        res.status(200).end();
    });
    req.pipe(busboy);
});

最後に、request-promise ライブラリはストリームの使用を推奨しないため、request ライブラリの使用を検討することをお勧めします。詳細については、github リポジトリを参照してください: https://github.com/request/request-promise

于 2016-02-21T20:17:02.537 に答える