mirror of
https://github.com/taobataoma/meanTorrent.git
synced 2026-07-07 20:51:33 +02:00
Save profile images to Amazon S3 (#1857)
* Profile Image to S3 * Delete image from S3 Fix file deletion * S3 refactoring
This commit is contained in:
@@ -211,6 +211,15 @@ $ docker run -p 27017:27017 -d --name db mongo
|
||||
$ docker run -p 3000:3000 --link db:db_1 mean
|
||||
```
|
||||
|
||||
### Amazon S3 configuration
|
||||
|
||||
To save the profile images to S3, simply set those environment variables:
|
||||
UPLOADS_STORAGE: s3
|
||||
S3_BUCKET: the name of the bucket where the images will be saved
|
||||
S3_ACCESS_KEY_ID: Your S3 access key
|
||||
S3_SECRET_ACCESS_KEY: Your S3 access key password
|
||||
|
||||
|
||||
## Getting Started With MEAN.JS
|
||||
You have your application running, but there is a lot of stuff to understand. We recommend you go over the [Official Documentation](http://meanjs.org/docs.html).
|
||||
In the docs we'll try to explain both general concepts of MEAN components and give you some guidelines to help you improve your development process. We tried covering as many aspects as possible, and will keep it updated by your request. You can also help us develop and improve the documentation by checking out the *gh-pages* branch of this repository.
|
||||
|
||||
9
config/env/default.js
vendored
9
config/env/default.js
vendored
@@ -45,7 +45,16 @@ module.exports = {
|
||||
illegalUsernames: ['meanjs', 'administrator', 'password', 'admin', 'user',
|
||||
'unknown', 'anonymous', 'null', 'undefined', 'api'
|
||||
],
|
||||
aws: {
|
||||
s3: {
|
||||
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
||||
bucket: process.env.S3_BUCKET
|
||||
}
|
||||
},
|
||||
uploads: {
|
||||
// Storage can be 'local' or 's3'
|
||||
storage: process.env.UPLOADS_STORAGE || 'local',
|
||||
profile: {
|
||||
image: {
|
||||
dest: './modules/users/client/img/profile/uploads/',
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<ul class="nav navbar-nav navbar-right" ng-show="vm.authentication.user">
|
||||
<li class="dropdown" uib-dropdown>
|
||||
<a class="dropdown-toggle user-header-dropdown-toggle" uib-dropdown-toggle role="button">
|
||||
<img ng-src="/{{vm.authentication.user.profileImageURL}}" alt="{{vm.authentication.user.displayName}}" class="header-profile-image" />
|
||||
<img ng-src="{{vm.authentication.user.profileImageURL}}" alt="{{vm.authentication.user.displayName}}" class="header-profile-image" />
|
||||
<span ng-bind="vm.authentication.user.displayName"></span> <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<form class="signin form-horizontal">
|
||||
<fieldset>
|
||||
<div class="form-group text-center">
|
||||
<img ngf-src="vm.fileSelected ? picFile : '/' + vm.user.profileImageURL" alt="{{vm.user.displayName}}" class="img-thumbnail user-profile-picture" ngf-drop>
|
||||
<img ngf-src="vm.fileSelected ? picFile : vm.user.profileImageURL" alt="{{vm.user.displayName}}" class="img-thumbnail user-profile-picture" ngf-drop>
|
||||
</div>
|
||||
<div ng-show="vm.loading" class="form-group text-center">
|
||||
<img ng-src="/modules/core/client/img/loaders/loader.gif" height="50" width="50" alt="Loading image...">
|
||||
|
||||
@@ -9,12 +9,27 @@ var _ = require('lodash'),
|
||||
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')),
|
||||
mongoose = require('mongoose'),
|
||||
multer = require('multer'),
|
||||
multerS3 = require('multer-s3'),
|
||||
aws = require('aws-sdk'),
|
||||
amazonS3URI = require('amazon-s3-uri'),
|
||||
config = require(path.resolve('./config/config')),
|
||||
User = mongoose.model('User'),
|
||||
validator = require('validator');
|
||||
|
||||
var whitelistedFields = ['firstName', 'lastName', 'email', 'username'];
|
||||
|
||||
var useS3Storage = config.uploads.storage === 's3' && config.aws.s3;
|
||||
var s3;
|
||||
|
||||
if (useS3Storage) {
|
||||
aws.config.update({
|
||||
accessKeyId: config.aws.s3.accessKeyId,
|
||||
secretAccessKey: config.aws.s3.secretAccessKey
|
||||
});
|
||||
|
||||
s3 = new aws.S3();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user details
|
||||
*/
|
||||
@@ -57,10 +72,24 @@ exports.update = function (req, res) {
|
||||
exports.changeProfilePicture = function (req, res) {
|
||||
var user = req.user;
|
||||
var existingImageUrl;
|
||||
var multerConfig;
|
||||
|
||||
|
||||
if (useS3Storage) {
|
||||
multerConfig = {
|
||||
storage: multerS3({
|
||||
s3: s3,
|
||||
bucket: config.aws.s3.bucket,
|
||||
acl: 'public-read'
|
||||
})
|
||||
};
|
||||
} else {
|
||||
multerConfig = config.uploads.profile.image;
|
||||
}
|
||||
|
||||
// Filtering to upload only images
|
||||
var multerConfig = config.uploads.profile.image;
|
||||
multerConfig.fileFilter = require(path.resolve('./config/lib/multer')).imageFileFilter;
|
||||
|
||||
var upload = multer(multerConfig).single('newProfilePicture');
|
||||
|
||||
if (user) {
|
||||
@@ -95,7 +124,9 @@ exports.changeProfilePicture = function (req, res) {
|
||||
|
||||
function updateUser() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
user.profileImageURL = config.uploads.profile.image.dest + req.file.filename;
|
||||
user.profileImageURL = config.uploads.storage === 's3' && config.aws.s3 ?
|
||||
req.file.location :
|
||||
'/' + req.file.path;
|
||||
user.save(function (err, theuser) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
@@ -109,24 +140,47 @@ exports.changeProfilePicture = function (req, res) {
|
||||
function deleteOldImage() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (existingImageUrl !== User.schema.path('profileImageURL').defaultValue) {
|
||||
fs.unlink(existingImageUrl, function (unlinkError) {
|
||||
if (unlinkError) {
|
||||
if (useS3Storage) {
|
||||
try {
|
||||
var { region, bucket, key } = amazonS3URI(existingImageUrl);
|
||||
var params = {
|
||||
Bucket: config.aws.s3.bucket,
|
||||
Key: key
|
||||
};
|
||||
|
||||
// If file didn't exist, no need to reject promise
|
||||
if (unlinkError.code === 'ENOENT') {
|
||||
console.log('Removing profile image failed because file did not exist.');
|
||||
return resolve();
|
||||
}
|
||||
s3.deleteObject(params, function (err) {
|
||||
if (err) {
|
||||
console.log('Error occurred while deleting old profile picture.');
|
||||
console.log('Check if you have sufficient permissions : ' + err);
|
||||
}
|
||||
|
||||
console.error(unlinkError);
|
||||
|
||||
reject({
|
||||
message: 'Error occurred while deleting old profile picture'
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
} catch (err) {
|
||||
console.warn(`${existingImageUrl} is not a valid S3 uri`);
|
||||
|
||||
return resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fs.unlink(path.resolve('.' + existingImageUrl), function (unlinkError) {
|
||||
if (unlinkError) {
|
||||
|
||||
// If file didn't exist, no need to reject promise
|
||||
if (unlinkError.code === 'ENOENT') {
|
||||
console.log('Removing profile image failed because file did not exist.');
|
||||
return resolve();
|
||||
}
|
||||
|
||||
console.error(unlinkError);
|
||||
|
||||
reject({
|
||||
message: 'Error occurred while deleting old profile picture'
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"acl": "~0.4.10",
|
||||
"amazon-s3-uri": "0.0.3",
|
||||
"async": "~2.5.0",
|
||||
"aws-sdk": "^2.104.0",
|
||||
"body-parser": "~1.17.1",
|
||||
"bower": "~1.8.0",
|
||||
"chalk": "~2.1.0",
|
||||
@@ -79,6 +81,7 @@
|
||||
"mongoose": "~4.11.3",
|
||||
"morgan": "~1.8.1",
|
||||
"multer": "~1.3.0",
|
||||
"multer-s3": "^2.7.0",
|
||||
"nodemailer": "~4.0.1",
|
||||
"owasp-password-strength-test": "~1.3.0",
|
||||
"passport": "~0.3.2",
|
||||
|
||||
Reference in New Issue
Block a user