使用NodeJS将文件上传到Amazon S3

尝试将文件上传到S3存储桶时遇到问题。一切正常,除了我的文件参数似乎不合适。我正在使用Amazon S3 SDK从Node.js上载到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');

}

});

});

};

Bodyparam

设置为类似字符串的"hello"效果很好。根据doc,Bodyparam必须获取 (缓冲区,类型数组,Blob,字符串,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中间件支持文件上传。该中间件所做的是获取上载的文件,将其写入本地文件系统,然后设置req.files为上载的文件。

您的路由配置看起来不错,问题似乎出在您的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)。

相反,我建议您使用的是我一直在研究的模块S3FS,它提供了与Node.JS中本机FS相似的接口,但抽象了一些细节,例如分段上传和S3

api (以及添加一些其他功能,例如递归方法)。

如果要拉入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凭证的模块,然后创建存储桶(如果不存在)。然后,当请求上传文件时,我们将打开一个流到该文件的流,并使用该流将文件写入S3到指定路径。这将在后台处理多部分上传文件(如果需要),并且具有通过流完成操作的好处,因此您无需等待读取整个文件即可开始上传文件。

如果愿意,可以将代码更改为Promises的回调。或将pipe()方法与事件侦听器一起使用来确定结束/错误。

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

以上是 使用NodeJS将文件上传到Amazon S3 的全部内容, 来源链接: utcz.com/qa/432806.html

回到顶部