Skip to content

Instantly share code, notes, and snippets.

@adon-at-work
Last active April 3, 2023 18:10
Show Gist options
  • Star 61 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save adon-at-work/26c8a8e0a1aee5ded03c to your computer and use it in GitHub Desktop.
Save adon-at-work/26c8a8e0a1aee5ded03c to your computer and use it in GitHub Desktop.
Sample File Upload From Multer to S3
var AWS = require('aws-sdk'),
fs = require('fs');
// http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html#Credentials_from_Disk
AWS.config.loadFromPath('./aws-config.json');
// assume you already have the S3 Bucket created, and it is called ierg4210-shopxx-photos
var photoBucket = new AWS.S3({params: {Bucket: 'ierg4210-shopxx-photos'}});
function uploadToS3(file, destFileName, callback) {
photoBucket
.upload({
ACL: 'public-read',
Body: fs.createReadStream(file.path),
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);
}
var express = require('express'),
app = express(),
multer = require('multer');
app.get('/upload', function (req, res) {
res.status(200)
.send('<form method="POST" enctype="multipart/form-data">'
+ '<input type="file" name="file1"/><input type="submit"/>'
+ '</form>')
.end();
})
app.post('/upload', multer({limits: {fileSize:10*1024*1024}}), function (req, res) {
if (!req.files || !req.files.file1) {
return res.status(403).send('expect 1 file upload named file1').end();
}
var file1 = req.files.file1;
// this is mainly for user friendliness. this field can be freely tampered by attacker.
if (!/^image\/(jpe?g|png|gif)$/i.test(file1.mimetype)) {
return res.status(403).send('expect image file').end();
}
var pid = '10000' + parseInt(Math.random() * 10000000);
uploadToS3(file1, pid, 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();
})
})
app.listen(process.env.PORT || 3000, function () {
console.log('Example Server listening at port ' + (process.env.PORT || 3000));
});
{
"name": "multer-to-s3-sample",
"version": "1.0.0",
"description": "",
"main": "multer-to-s3.js",
"dependencies": {
"aws-sdk": "^2.1.17",
"express": "^4.12.2",
"multer": "^0.1.8"
},
"author": "Adonis Fung",
"license": "BSD"
}
@jimgong92
Copy link

I'm getting a bug with this - I think .array('file1') has to be appended to the multer() call, or even better would be to use .single('file1') and refactor the request handling to use req.file instead of req.files.

@silveur
Copy link

silveur commented Sep 2, 2015

Thanks a lot for this

@OriginalEXE
Copy link

Hi, I just published a npm package that adds s3 as a StorageEngine to multer: https://www.npmjs.com/package/multer-storage-s3

Feedback appreciated :)

@stephanelpaul
Copy link

or append .single('file'), so you can access req.file

@mary-dean
Copy link

Of all the "how to upload a file" demos I have examined in the past week, yours was the ONLY one that worked right out of the box. Incredibly helpful. In case people don't know, you can upload to a "folder" on S3 by prepending "foldername/" to the file name. I know these aren't real 'folders' but it does help keep your archive organized. Also, you can access the other fields in your form through req.body, so, for example, you could include req.body.userName as part of your S3 file name. I am using your code to create an archive of scanned historical photos and other documents from my extended family, and it's working beautifully. Thanks.

@roydondsouza
Copy link

Thank you very much. I just got a pointer to a problem I was stuck with.

@mmowris
Copy link

mmowris commented May 22, 2017

Hey @adon-at-work - question on this. I've changed your code to include middleware multer().single('file1') and it compiles, but I can't seem to get it to run with this simple command.. any insight here?

Can't get req.files to exist... or find any files in req, req.body, req.query, req.params, etc etc.

curl -i -X POST -F "file1=@image.png" http://localhost:3000/api/photos/

cc: @stephanep @jimgong92 @mary-dean @roydondsouza - any of you get this to work, and if so how do you access the file once uploaded? where can I show output?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment