Created
July 16, 2013 17:07
-
-
Save psaia/6010602 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
mongoose = require 'mongoose' | |
helpers = require '../libs/helpers' | |
config = require "../config" | |
gm = require "gm" | |
path = require "path" | |
os = require "os" | |
crypto = require "crypto" | |
fs = require "fs" | |
request = require "request" | |
# Basic schema. | |
Image = new mongoose.Schema | |
created: { type: Date, default: Date.now } | |
name: { type: String, default: "", required: true } | |
size: { type: Array } # [w,h] | |
body: { type: String, default: "" } | |
# Sizes to create for images. | |
SIZES = | |
avatar: | |
w: 100 | |
h: 100 | |
c: true | |
large: | |
w: 1500 | |
h: 1500 | |
c: false | |
medium: | |
w: 600 | |
h: 600 | |
c: false | |
small: | |
w: 300 | |
h: 300 | |
c: false | |
# Method to generate name for image. | |
Image.statics.randomName = -> Math.round(Date.now() / 1000) + crypto.randomBytes(20).toString('hex') | |
# Will create a new original image, generate all sizes, and return the object. | |
Image.statics.importLocal = (tmpFile, fileName, fn) -> | |
return fn new Error "Temp file (#{tmpFile}) does not exist." if not fs.existsSync tmpFile | |
finalPhotoFile = path.join config.IMAGE_DIR, "#{fileName}.png" # Where the new file will be stored. | |
gm(tmpFile).autoOrient().write finalPhotoFile, (err) -> # Convert the photo & save. | |
fs.unlinkSync tmpFile # Remove temp file. | |
return fn err if err | |
gm(finalPhotoFile).size (err, size) -> # Get size information to store. | |
return fn err if err | |
img = new Model # Create the new model. | |
name: fileName | |
size: [size.width, size.height] | |
img.generate (err) -> | |
return fn err if err | |
img.save (err) -> # Save the new file's model and return. | |
return fn err if err | |
fn null, img | |
# This will import any image via HTTP and save it into the system and return the Image model. | |
Image.statics.import = (url, fn) -> | |
throw new Error "A 'url' is required." if not url | |
name = Model.randomName() # A random string. | |
tmpFile = path.join os.tmpdir(), name # Where the downloaded file is temporarily stored. | |
writeStream = fs.createWriteStream(tmpFile) # Write stream for new file. | |
writeStream.on "error", -> fn true # Oops. | |
writeStream.on "finish", -> # Photo loaded to temp directory. | |
Model.importLocal tmpFile, name, (err, image) -> | |
return fn err if err | |
fn null, image | |
request(url).pipe(writeStream) # Start the download of the image. | |
# Generate all sizes for an image. | |
Image.methods.generate = (fn) -> | |
throw new Error "A callback function must be specified." if not fn | |
self = @ | |
count = 0 | |
names = for name, obj of SIZES then name | |
objs = for name, obj of SIZES then obj | |
create = -> | |
if names[count] | |
if objs[count].c # If we're cropping. | |
g = self.gm() | |
if self.size[0] > self.size[1] # Width is larger. | |
g.resize null, objs[count].h # Resize by height. | |
else # Height is larger. | |
g.resize objs[count].w, null # Resize by width. | |
g.crop objs[count].w, objs[count].h | |
else # Else just resize and restrain. | |
g = self.gm().resize objs[count].w, objs[count].h | |
g.write self.path(names[count], true), (err) -> | |
return fn err if err | |
create count++ # Create the next image size. | |
else | |
fn null | |
create() | |
# An instance of GrapicsMagick instance for the original image. | |
# This will be useful for when we need to make a cropper. | |
Image.methods.gm = -> gm(this.path(null, true)) | |
# Can return the full or relative path to an image. | |
Image.methods.path = (name = null, absolute = false) -> | |
imageName = (if name then "#{this.name}-#{name}" else this.name) + ".png" | |
dir = if absolute then path.join process.cwd(), config.IMAGE_DIR else config.IMAGE_DIR | |
path.join "/", dir, imageName | |
# Called when the document is removed. Removed all accociated images to model. | |
Image.pre "remove", (done) -> | |
self = @ | |
count = 0 | |
names = for name, obj of SIZES then name | |
objs = for name, obj of SIZES then obj | |
fs.unlinkSync this.path null, true if fs.existsSync this.path null, true # Remove original. | |
rm = -> | |
if names[count] | |
fs.unlinkSync self.path names[count], true if fs.existsSync self.path names[count], true | |
rm count++ | |
else | |
done() | |
rm() | |
# Create & export the mongoose model. | |
module.exports = Model = mongoose.model 'Image', Image |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment