Skip to content

Instantly share code, notes, and snippets.

@psaia
Created July 16, 2013 17:07
Show Gist options
  • Save psaia/6010602 to your computer and use it in GitHub Desktop.
Save psaia/6010602 to your computer and use it in GitHub Desktop.
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