使用NodeJS将file upload到Amazon S3

试图将file upload到我的S3存储桶时遇到问题。 一切工作除了我的文件参数似乎不合适。 我正在使用Amazon S3 sdk从nodejs上传到s3。

这些是我的路线设置:

var multiparty = require('connect-multiparty'), multipartyMiddleware = multiparty(); app.route('/api/items/upload').post(multipartyMiddleware, items.upload); 

这是items.upload()函数:

 exports.upload = function(req, res) { var file = req.files.file; var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}}); s3bucket.createBucket(function() { var params = { Key: file.name, Body: file }; s3bucket.upload(params, function(err, data) { console.log("PRINT FILE:", file); if (err) { console.log('ERROR MSG: ', err); } else { console.log('Successfully uploaded data'); } }); }); }; 

设置Body参数像一个string"hello"工作正常。 根据doc , Body参数必须取(Buffer,Typed Array,Blob,String,ReadableStream)对象数据。 但是,上传文件对象失败,并显示以下错误消息:

 [Error: Unsupported body payload object] 

这是文件对象:

 { fieldName: 'file', originalFilename: 'second_fnp.png', path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png', headers: { 'content-disposition': 'form-data; name="file"; filename="second_fnp.png"', 'content-type': 'image/png' }, ws: { _writableState: { highWaterMark: 16384, objectMode: false, needDrain: true, ending: true, ended: true, finished: true, decodeStrings: true, defaultEncoding: 'utf8', length: 0, writing: false, sync: false, bufferProcessing: false, onwrite: [Function], writecb: null, writelen: 0, buffer: [], errorEmitted: false }, writable: true, domain: null, _events: { error: [Object], close: [Object] }, _maxListeners: 10, path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png', fd: null, flags: 'w', mode: 438, start: undefined, pos: undefined, bytesWritten: 261937, closed: true }, size: 261937, name: 'second_fnp.png', type: 'image/png' } 

任何帮助将不胜感激!

所以看起来这里有一些事情是错误的。 根据您的文章,您似乎正在尝试使用connect-multiparty中间件来支持file upload。 这个中间件做的是把上传的文件,写入本地文件系统,然后设置req.files到上传的文件。

你的路线的configuration看起来不错,问题看起来与你的items.upload()函数。 特别是在这个部分:

 var params = { Key: file.name, Body: file }; 

正如我在回答开始时提到的, connect-multiparty将文件写入本地文件系统,因此您需要打开文件并读取文件,然后上载,然后在本地文件系统上删除它。

这就是说你可以更新你的方法如下所示:

 var fs = require('fs'); exports.upload = function (req, res) { var file = req.files.file; fs.readFile(file.path, function (err, data) { if (err) throw err; // Something went wrong! var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}}); s3bucket.createBucket(function () { var params = { Key: file.originalFilename, //file.name doesn't exist as a property Body: data }; s3bucket.upload(params, function (err, data) { // Whether there is an error or not, delete the temp file fs.unlink(file.path, function (err) { if (err) { console.error(err); } console.log('Temp File Delete'); }); console.log("PRINT FILE:", file); if (err) { console.log('ERROR MSG: ', err); res.status(500).send(err); } else { console.log('Successfully uploaded data'); res.status(200).end(); } }); }); }); }; 

这样做是从本地文件系统读取上传的文件,然后将其上传到S3,然后删除临时文件并发送响应。

这种方法存在一些问题。 首先,它不是那么高效,因为对于大文件,在写入之前您将加载整个文件。 其次,这个过程不支持大文件的多部分上传(我认为在你必须做一个多部分上传之前的截止是5 Mb)。

我会build议,而不是你使用我一直在工作的模块称为S3FS ,它提供了一个类似的接口,在本地FS在Node.JS,但摘要了一些细节,如多部分上传和S3 API (以及添加一些附加function,如recursion方法)。

如果你要拉入S3FS库,你的代码看起来像这样:

 var fs = require('fs'), S3FS = require('s3fs'), s3fsImpl = new S3FS('mybucketname', { accessKeyId: XXXXXXXXXXX, secretAccessKey: XXXXXXXXXXXXXXXXX }); // Create our bucket if it doesn't exist s3fsImpl.create(); exports.upload = function (req, res) { var file = req.files.file; var stream = fs.createReadStream(file.path); return s3fsImpl.writeFile(file.originalFilename, stream).then(function () { fs.unlink(file.path, function (err) { if (err) { console.error(err); } }); res.status(200).end(); }); }; 

这将做的是实例化提供的存储桶和AWS凭证模块,然后创build存储桶,如果它不存在。 然后,当请求通过上传文件时,我们将打开一个文件stream,并用它来将文件写入S3到指定的path。 这将处理幕后的多部分上传片段(如果需要的话),并有利于通过stream来完成,因此您无需等待在开始上传之前阅读整个文件。

如果您愿意,可以将代码更改为来自Promises的callback。 或者使用带有事件监听器的pipe()方法来确定结束/错误。

如果您正在寻找其他方法,请查看s3fs的文档,如果您正在寻找其他方法或遇到问题,请随时打开该问题。

我发现以下是一个工作解决scheme::

 npm install aws-sdk 

一旦你安装了aws-sdk,使用下面的代码replace你所需的值。

 var AWS = require('aws-sdk'); var fs = require('fs'); var s3 = new AWS.S3(); // Bucket names must be unique across all S3 users var myBucket = 'njera'; var myKey = 'jpeg'; //for text file //fs.readFile('demo.txt', function (err, data) { //for Video file //fs.readFile('demo.avi', function (err, data) { //for image file fs.readFile('demo.jpg', function (err, data) { if (err) { throw err; } params = {Bucket: myBucket, Key: myKey, Body: data }; s3.putObject(params, function(err, data) { if (err) { console.log(err) } else { console.log("Successfully uploaded data to myBucket/myKey"); } }); }); 

我在这里find关于这个主题的完整教程,以防你正在寻找参考::


如何使用node.js在amazon s3上传文件(文本/图像/video)