使用aws-sdk和Node / Express将简单的file upload到S3

我错过了我所做的一切,下面是我所拥有的:

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> 

Port 5000是我的Node.js服务器的端口。

在这个例子中,我正在使用POST /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"); } }); }); } 

现在我想发布我正在发布的文件,这是问题出现的地方。

 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"); } }); }); }); } 

我得到的错误是:

TypeError:无法读取未定义的属性“path”

事实上files是完全空的。

我假设我失去了很明显的东西,但我似乎无法find它。

你需要像multer一样处理多部分上传。 这是一个使用aws-sdk将file upload到s3的例子。

 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"); } }); 

最新回答@ Dec-2016 [新]

使用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!'); }); 

最新回答@ Mar-2016 [Old-One]

编辑1 使用 multer@1.1.0 multer-s3@1.4.1 以下摘录

 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!'); }); 

对于完整的运行示例克隆express_multer_s3回购和运行node app

听起来你可能没有expressParser中间件设置。 你可以发布你的整个服务器文件(app.js,server.js,你有什么)

而不是multipart / form-data,你可以尝试使用image / png或任何正确的mimetypes。

您需要在中间件集合中使用诸如multer之类的东西来处理multipart/form-data ,并填充req.files 。 从doco:

 var express = require('express') var multer = require('multer') var app = express() app.use(multer({ dest: './uploads/'})) 

现在req.files.image.path应该填充在你的app.post函数中。

它看起来像你的req.files.image是未定义的。 console.log出req.files.image返回的内容,看看是否可以从那里出发。

这个堆栈溢出是我发现解释如何让Node到S3工作的最佳答案。

AWS尝试将消息发送给我的S3 Bucket(Node.js)

这除了一些我不得不破解的东西来完成所有的工作。 在我的情况下,我正在使用一个MEAN堆栈应用程序,所以我正在使用的节点文件是一个路由文件。

我的aconfig.json文件与亚马逊证书看起来像这样:

 { "accessKeyId": "*****YourAccessKey****", "secretAccessKey": "***YourSecretKey****" } 

path文件的最终内容看起来像下面粘贴的文件。

 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, '&lt;') + '<br/><img src="' + data.Location.replace(/"/g, '&quot;') + '"/>') .end(); }); console.log('uploading now...'); }); 

这花了我一些时间才能最终得到工作,但如果你设置下面的路线,更新sampleFile JSON指向您的系统上的一个真实的文件,并与邮递员打它将发布一个文件到您的S3帐户。

希望这可以帮助