Last active
September 11, 2015 21:21
-
-
Save gotvitch/4c9f918e836d6c6b16f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Save a image | |
image_options = | |
styles: | |
# Will resize to 250x250 by cropping in the center | |
# 2000x1000 => 250x250 | |
small: | |
size: '250x250' | |
resize: '250x250^' | |
gravity: 'Center' | |
crop: '250x250' | |
# Will resize without crop, keep the ratio, max height and width will be 800 | |
# The `>` is to not enlarge the image | |
# 2000x1000 => 800x400 | |
medium: | |
size: '800x800' | |
resize: '800x800>' | |
# Will resize without crop, keep the ratio, max height and width will be 800 | |
# The `>` is to not enlarge the image | |
# 2000x1000 => 1600x800 | |
normal: | |
size: '1600x1600' | |
resize: '1600x1600>' | |
original: {} | |
_storage.saveImage user_object_id.toString(), file_path, image_options, ( err, image ) -> | |
return callback err if err? | |
doc = | |
user_id: user_object_id | |
created_at: new Date() | |
file_id: image.id | |
_.extend photo_doc, _.pick image, [ | |
'ext' | |
'format' | |
'height' | |
'orientation' | |
'width' | |
] | |
# Save in mongo | |
# Set the url in fromDocument or toJSON | |
photo.urls = _storage.getImageUrls photo.user_id, photo.file_id, photo.ext, Photo.styles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
debug = (require 'debug') 'helpers:storage' | |
_ = require 'lodash' | |
async = require 'async' | |
aws = require 'aws-sdk' | |
gm = require 'gm' | |
moment = require 'moment-timezone' | |
path = require 'path' | |
module.exports = ( _config, _geo, _utils ) -> | |
debug "load" | |
s3Client = new aws.S3 | |
accessKeyId: _config.aws.access_key | |
secretAccessKey: _config.aws.secret_key | |
# See: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#constructor-property | |
_storage = | |
# @todo Parse EXIF info | |
# @method saveImage | |
# @description | |
# | |
# @param {String} file_path: | |
# @param {Object} options: | |
# @param {Function(err, image)} callback: | |
# - {Error} err: Error in case of failure | |
# - {Object} image: Image information with the following format: | |
# { | |
# id: String, | |
# format: String, | |
# taken_at: String, | |
# orientation: String, | |
# iso: String, | |
# aperture: String, | |
# shutter_speed: String, | |
# focal_length: String, | |
# camera: String | |
# } | |
# | |
saveImage: ( user_id, file_path, options, callback ) -> | |
options ?= {} | |
keys = _.keys( options.styles ) | |
gm( file_path ).identify '%m\n%wx%h\n%[EXIF:*]', ( err, info ) -> | |
return callback err if err? | |
lines = info.split '\n' | |
[ format, size ] = lines | |
size = size.split 'x' | |
size = | |
width: parseInt size[ 0 ] | |
height: parseInt size[ 1 ] | |
exif_info = {} | |
for i in [2...lines.length] by 1 | |
line = lines[ i ] | |
line_split = line.split '=' | |
exif_info[ line_split[ 0 ] ] = line_split[ 1 ] | |
image = | |
# Generate a unique file ID | |
id: _utils.generateId() | |
format: format.toLowerCase() | |
ext: path.extname( file_path ).toLowerCase().substring( 1 ) | |
# By default use the size detect by Graphick Magic | |
# But try to get the size from exif for orientation detection | |
width: size.width | |
height: size.height | |
# See http://owl.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html | |
if !_.isEmpty( exif_info ) | |
fields = | |
taken_at: 'DateTimeOriginal' | |
orientation: 'Orientation' | |
iso: 'ISOSpeedRatings' | |
aperture: 'FNumber' | |
shutter_speed: 'ExposureTime' | |
focal_length: 'FocalLength' | |
_utils.copyFields exif_info, image, fields | |
if exif_info['ExifImageWidth']? && exif_info['ExifImageLength']? | |
image.width = parseInt exif_info['ExifImageWidth'] | |
image.height = parseInt exif_info['ExifImageLength'] | |
# Switch the width and height | |
if exif_info['Orientation'] in [ '6', '8' ] | |
height = image.width | |
image.width = image.height | |
image.height = height | |
async.each( | |
_.keys( options.styles ) | |
, ( style_name, callback ) -> | |
style = options.styles[ style_name ] | |
gmObject = gm file_path | |
gmObject.out '-auto-orient' | |
_.each style, (value, key) -> | |
if key == 'size' | |
gmObject.in "-#{ key }", value | |
else | |
gmObject.out "-#{ key }", value | |
folder = "#{ user_id }/" | |
filename = "#{ folder }#{ image.id }_#{ style_name }.#{ image.ext }" | |
gmObject.stream ( err, stdout, stderr ) -> | |
return callback err if err? | |
object = | |
Bucket: _config.aws.bucket | |
Key: filename | |
Body: stdout | |
ACL: 'public-read' | |
ContentType: "image/#{ image.format }" | |
# see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property | |
s3Client.upload object, ( err, data ) -> | |
return callback err if err? | |
return callback null | |
, ( err ) -> | |
return callback null, image | |
) | |
deleteImage: ( user_id, file_id, ext, styles, callback ) -> | |
folder = "#{ user_id }/" | |
params = | |
Bucket: _config.aws.bucket | |
Delete: | |
Objects: _.map _.keys( styles ), ( style_name ) -> return { Key: "#{ folder }#{ file_id }_#{ style_name }.#{ ext }" } | |
# see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property | |
s3Client.deleteObjects params, ( err, data ) -> | |
return callback err if err? | |
debug "data", data | |
return callback null | |
deleteImages: ( user_id, files, styles, callback ) -> | |
folder = "#{ user_id }/" | |
objects = [] | |
for file in files | |
for style_name, style of styles | |
objects.push( { Key: "#{ folder }#{ file.id }_#{ style_name }.#{ file.ext }" } ) | |
chunked_objects = _.chunk( objects, 300 ) | |
async.eachSeries( | |
chunked_objects | |
, ( objects ) -> | |
params = | |
Bucket: _config.aws.bucket | |
Delete: | |
Objects: objects | |
# see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property | |
s3Client.deleteObjects params, ( err, data ) -> | |
return callback err if err? | |
debug "deleteObjects result", data | |
return callback null | |
, callback | |
) | |
getImageUrls: ( user_id, file_id, ext, styles ) -> | |
urls = {} | |
for style_name in _.keys styles | |
urls[ style_name ] = "#{ _config.aws.cdn }/#{ user_id }/#{ file_id }_#{ style_name }.#{ ext }" | |
return urls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment