Streaming file to S3 “Error: stream ended unexpectedly”

风流意气都作罢 提交于 2019-12-06 11:36:29

There is an example for S3 on the node-multiparty source.

https://github.com/andrewrk/node-multiparty/tree/master/examples

var http = require('http'),
    util = require('util'),
    multiparty = require('../'),
    knox = require('knox'),
    Batch = require('batch'),
    PORT = process.env.PORT || 27372

var s3Client = knox.createClient({
    secure: false,
    key: process.env.S3_KEY,
    secret: process.env.S3_SECRET,
    bucket: process.env.S3_BUCKET,
});

var server = http.createServer(function(req, res) {
    if (req.url === '/') {
        res.writeHead(200, {
            'content-type': 'text/html'
        });
        res.end(
            '<form action="/upload" enctype="multipart/form-data" method="post">' +
            '<input type="text" name="path"><br>' +
            '<input type="file" name="upload"><br>' +
            '<input type="submit" value="Upload">' +
            '</form>'
        );
    } else if (req.url === '/upload') {
        var headers = {
            'x-amz-acl': 'public-read',
        };
        var form = new multiparty.Form();
        var batch = new Batch();
        batch.push(function(cb) {
            form.on('field', function(name, value) {
                if (name === 'path') {
                    var destPath = value;
                    if (destPath[0] !== '/') destPath = '/' + destPath;
                    cb(null, destPath);
                }
            });
        });
        batch.push(function(cb) {
            form.on('part', function(part) {
                if (!part.filename) return;
                cb(null, part);
            });
        });
        batch.end(function(err, results) {
            if (err) throw err;
            form.removeListener('close', onEnd);
            var destPath = results[0],
                part = results[1];

            headers['Content-Length'] = part.byteCount;
            s3Client.putStream(part, destPath, headers, function(err, s3Response) {
                if (err) throw err;
                res.statusCode = s3Response.statusCode;
                s3Response.pipe(res);
                console.log("https://s3.amazonaws.com/" + process.env.S3_BUCKET + destPath);
            });
        });
        form.on('close', onEnd);
        form.parse(req);

    } else {
        res.writeHead(404, {
            'content-type': 'text/plain'
        });
        res.end('404');
    }

    function onEnd() {
        throw new Error("no uploaded file");
    }
});
server.listen(PORT, function() {
    console.info('listening on http://0.0.0.0:' + PORT + '/');
});

````

The crux to the solution is to not use the (apparently deprecated) bodyParser(). I'm not certain what it does, but it screws up the form's parts that multiparty uses. So instead, if you have the same problem I had, instead of using bodyParser(), use the things you need explicitely (for example):

app.use(express.urlencoded());
app.use(express.json());

And then for your multipart stuff, just use multiparty to parse the body yourself. The author of multiparty gives more info on the subject.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!