node.js 使用 aws-sdk 和 Node/Express 将简单的文件上传到 S3
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17930204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple file upload to S3 using aws-sdk and Node/Express
提问by abritez
I am at a loss of what I am doing wrong, here is what I have:
我不知道我做错了什么,这是我所拥有的:
HTML
HTML
<html>
<body>
<form method="POST" action="/upload" enctype="multipart/form-data">
<div class="field">
<label for="image">Image Upload</label>
<input type="file" name="image" id="image">
</div>
<input type="submit" class="btn" value="Save">
</form>
</body>
</html>
Port5000 is my Node.jsserver's port.
Port5000 是我的Node.js服务器的端口。
In this example I am using POSTto /upload, and it works fine.
在这个例子中,我使用POSTto /upload,它工作正常。
module.exports = function(app, models) {
var fs = require('fs');
var AWS = require('aws-sdk');
var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx";
var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx";
AWS.config.update({
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey
});
var s3 = new AWS.S3();
app.post('/upload', function(req, res){
var params = {
Bucket: 'makersquest',
Key: 'myKey1234.png',
Body: "Hello"
};
s3.putObject(params, function (perr, pres) {
if (perr) {
console.log("Error uploading data: ", perr);
} else {
console.log("Successfully uploaded data to myBucket/myKey");
}
});
});
}
Now I want to post the file that I am POSTing, which is where the problem arises.
现在我想贴出我正在POST处理的文件,这就是问题出现的地方。
module.exports = function(app, models) {
var fs = require('fs');
var AWS = require('aws-sdk');
var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx";
var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx";
AWS.config.update({
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey
});
var s3 = new AWS.S3();
app.post('/upload', function(req, res){
var path = req.files.image.path;
fs.readFile(path, function(err, file_buffer){
var params = {
Bucket: 'makersquest',
Key: 'myKey1234.png',
Body: file_buffer
};
s3.putObject(params, function (perr, pres) {
if (perr) {
console.log("Error uploading data: ", perr);
} else {
console.log("Successfully uploaded data to myBucket/myKey");
}
});
});
});
}
The error I get is:
我得到的错误是:
TypeError: Cannot read property 'path' of undefined
类型错误:无法读取未定义的属性“路径”
As a matter of fact filesis completely empty.
事实上files完全是空的。
I am assuming I am missing something pretty obvious but I can't seem to find it.
我假设我遗漏了一些很明显的东西,但我似乎找不到它。
回答by theRemix
You will need something like multerto handle multipart uploading.
Here is an example streaming your file upload to s3 using aws-sdk.
您将需要类似multer处理分段上传的功能。这是使用 .s3 将文件上传到 s3 的示例aws-sdk。
var multer = require('multer');
var AWS = require('aws-sdk');
var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx";
var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx";
AWS.config.update({
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey
});
var s3 = new AWS.S3();
app.use(multer({ // https://github.com/expressjs/multer
dest: './public/uploads/',
limits : { fileSize:100000 },
rename: function (fieldname, filename) {
return filename.replace(/\W+/g, '-').toLowerCase();
},
onFileUploadData: function (file, data, req, res) {
// file : { fieldname, originalname, name, encoding, mimetype, path, extension, size, truncated, buffer }
var params = {
Bucket: 'makersquest',
Key: file.name,
Body: data
};
s3.putObject(params, function (perr, pres) {
if (perr) {
console.log("Error uploading data: ", perr);
} else {
console.log("Successfully uploaded data to myBucket/myKey");
}
});
}
}));
app.post('/upload', function(req, res){
if(req.files.image !== undefined){ // `image` is the field name from your form
res.redirect("/uploads"); // success
}else{
res.send("error, no file chosen");
}
});
回答by Zeeshan Hassan Memon
Latest Answer @ Dec-2016 [New]
最新答案 @ 2016 年 12 月[新]
Use multer-s3for multipart uploading to s3 without saving on local disk as:
使用multer-s3分段上传到 s3 而不保存在本地磁盘上:
var express = require('express'),
aws = require('aws-sdk'),
bodyParser = require('body-parser'),
multer = require('multer'),
multerS3 = require('multer-s3');
aws.config.update({
secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
accessKeyId: 'XXXXXXXXXXXXXXX',
region: 'us-east-1'
});
var app = express(),
s3 = new aws.S3();
app.use(bodyParser.json());
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'bucket-name',
key: function (req, file, cb) {
console.log(file);
cb(null, file.originalname); //use Date.now() for unique file keys
}
})
});
//open in browser to see upload form
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
//use by upload form
app.post('/upload', upload.array('upl',1), function (req, res, next) {
res.send("Uploaded!");
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Latest Answer @ Mar-2016 [Old-One]
最新答案 @ Mar-2016 [旧一]
Edited 1use[email protected]and[email protected]for following snippet:
编辑了 1 次使用[email protected]和[email protected]以下代码段:
var express = require('express'),
bodyParser = require('body-parser'),
multer = require('multer'),
s3 = require('multer-s3');
var app = express();
app.use(bodyParser.json());
var upload = multer({
storage: s3({
dirname: '/',
bucket: 'bucket-name',
secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
accessKeyId: 'XXXXXXXXXXXXXXX',
region: 'us-east-1',
filename: function (req, file, cb) {
cb(null, file.originalname); //use Date.now() for unique file keys
}
})
});
//open in browser to see upload form
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
//use by upload form
app.post('/upload', upload.array('upl'), function (req, res, next) {
res.send("Uploaded!");
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
For complete running example clone express_multer_s3 repoand run node app.
对于完整的运行示例,克隆express_multer_s3 repo并运行node app。
回答by Rob Bennet
Sounds like you might not have the express bodyParser middleware setup. Can you post your entire server file (app.js, server.js, what have you)
听起来您可能没有设置 express bodyParser 中间件。你能发布你的整个服务器文件吗(app.js、server.js,你有什么)
回答by Vibgy
Instead of multipart/form-data, you can try using image/png or whatever the correct mime type is.
您可以尝试使用 image/png 或任何正确的 mime 类型,而不是 multipart/form-data。
回答by morloch
You need something like multerin your set of middleware to handle multipart/form-datafor you and populate req.files. From the doco:
您需要在您的一组中间件中使用multer 之类的东西来multipart/form-data为您处理并填充req.files. 从文件:
var express = require('express')
var multer = require('multer')
var app = express()
app.use(multer({ dest: './uploads/'}))
Now req.files.image.pathshould be populated in your app.postfunction.
现在req.files.image.path应该填充到您的app.post函数中。
回答by Surojit Paul
Simple S3 File Upload Without Multer
无需 Multer 的简单 S3 文件上传
var express = require('express')
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload());
var AWS = require('aws-sdk');
app.post('/imageUpload', async (req, res) => {
AWS.config.update({
accessKeyId: "ACCESS-KEY", // Access key ID
secretAccesskey: "SECRET-ACCESS-KEY", // Secret access key
region: "us-east-1" //Region
})
const s3 = new AWS.S3();
// Binary data base64
const fileContent = Buffer.from(req.files.uploadedFileName.data, 'binary');
// Setting up S3 upload parameters
const params = {
Bucket: 'BUKET-NAME',
Key: "test.jpg", // File name you want to save as in S3
Body: fileContent
};
// Uploading files to the bucket
s3.upload(params, function(err, data) {
if (err) {
throw err;
}
res.send({
"response_code": 200,
"response_message": "Success",
"response_data": data
});
});
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
回答by JasonPerr
This stack overflow was the best answer I found explaining exactly how to get Node to S3 working.
这个堆栈溢出是我找到的最好的答案,它解释了如何让 Node 到 S3 工作。
AWS Missing credentials when i try send something to my S3 Bucket (Node.js)
当我尝试向我的 S3 存储桶 (Node.js) 发送内容时,AWS 缺少凭证
This in addition to some more stuff I had to hack on to get it all working. In my situation I was using a MEAN stack application so my Node file I was working with was a route file.
除了一些我必须破解才能让它全部工作的东西之外。在我的情况下,我使用的是 MEAN 堆栈应用程序,因此我使用的 Node 文件是一个路由文件。
my aconfig.json file with the amazon credentials looks like this:
我的带有 amazon 凭据的 aconfig.json 文件如下所示:
{ "accessKeyId": "*****YourAccessKey****", "secretAccessKey": "***YourSecretKey****" }
The final contents of the route file look like the file pasted below.
路由文件的最终内容类似于下面粘贴的文件。
router.post('/sendToS3', function(req, res) {
var fs = require('fs');
var multer = require('multer');
var AWS = require('aws-sdk');
var path = require('path');
var awsCredFile = path.join(__dirname, '.', 'aconfig.json');
console.log('awsCredFile is');
console.log(awsCredFile);
AWS.config.loadFromPath(awsCredFile);
var s3 = new AWS.S3();
var photoBucket = new AWS.S3({params: {Bucket: 'myGreatBucketName'}});
var sampleFile = {
"_id" : 345345,
"fieldname" : "uploads[]",
"originalname" : "IMG_1030.JPG",
"encoding" : "7bit",
"mimetype" : "image/jpeg",
"destination" : "./public/images/uploads",
"filename" : "31a66c51883595e74ab7ae5e66fb2ab8",
"path" : "/images/uploads/31a66c51883595e74ab7ae5e66fb2ab8",
"size" : 251556,
"user" : "579fbe61adac4a8a73b6f508"
};
var filePathToSend = path.join(__dirname, '../public', sampleFile.path);
function uploadToS3(filepath, destFileName, callback) {
photoBucket
.upload({
ACL: 'public-read',
Body: fs.createReadStream(filepath),
Key: destFileName.toString(),
ContentType: 'application/octet-stream' // force download if it's accessed as a top location
})
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#httpUploadProgress-event
.on('httpUploadProgress', function(evt) { console.log(evt); })
// http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#send-property
.send(callback);
}
multer({limits: {fileSize:10*1024*1024}});
console.log('filePathToSend is ');
console.log(filePathToSend);
uploadToS3(filePathToSend, sampleFile.filename, function (err, data) {
if (err) {
console.error(err);
return res.status(500).send('failed to upload to s3').end();
}
res.status(200)
.send('File uploaded to S3: '
+ data.Location.replace(/</g, '<')
+ '<br/><img src="' + data.Location.replace(/"/g, '"') + '"/>')
.end();
});
console.log('uploading now...');
});
This took me a while to finally get working, but if you setup the route below, update the sampleFile JSON to point to a real file on your system and hit it with Postman it will publish a file to your S3 account.
这花了我一段时间才最终开始工作,但是如果您设置了下面的路线,请更新 sampleFile JSON 以指向您系统上的真实文件,并使用 Postman 命中它,它将向您的 S3 帐户发布一个文件。
Hope this helps
希望这可以帮助
回答by M1Reeder
It looks like your req.files.image is undefined. console.log out what req.files.image returns and see if you can go from there.
看起来您的 req.files.image 未定义。console.log out 什么 req.files.image 返回,看看你是否可以从那里去。

