Permalink
Browse files

Initial Commit

  • Loading branch information...
0 parents commit 0d093dddfed26cd19efecf52caa37aabfe18475b @mlmorg mlmorg committed Oct 22, 2012
Showing with 275 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +21 −0 LICENSE
  3. +5 −0 Makefile
  4. +24 −0 README.md
  5. +49 −0 lib/imagine-file.js
  6. +85 −0 lib/imagine-file/downloader.js
  7. +70 −0 lib/imagine-file/uploader.js
  8. +20 −0 package.json
@@ -0,0 +1 @@
+node_modules/
21 LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+Copyright (c) 2012 Brewster Inc., Matt Morgan, John Crepezzi
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
+lint:
+ find lib -name "*.js" -print0 | xargs -0 \
+ jslint --stupid --indent 2 --nomen --vars --maxlen 80
+
+.PHONY: lint
@@ -0,0 +1,24 @@
+# Imagine-File
+
+File storage for [Imagine](https://github.com/brewster/imagine).
+
+## Installation
+
+If you haven't already done so, make sure to install `imagine-file` in your
+Imagine folder:
+
+``` bash
+$ npm install imagine-file
+```
+
+Then, simply set your `config.json` file in Imagine to use the correct storage:
+
+```javascript
+"storage": "imagine-file"
+```
+
+## License
+
+Imagine-File is distributed under the MIT License. See
+[LICENSE](https://github.com/brewster/imagine-file/blob/master/LICENSE) for more
+details.
@@ -0,0 +1,49 @@
+"use strict";
+
+var crypto = require('crypto');
+var fs = require('fs');
+var winston = require('winston');
+var Uploader = require('./imagine-file/uploader');
+var Downloader = require('./imagine-file/downloader');
+
+var ImagineFile = function (config) {
+ config = config || {};
+ this.path = config.path || './data/';
+ this.configure();
+};
+
+ImagineFile.prototype = {
+
+ ready: function () {
+ return !!this.configured;
+ },
+
+ uploader: function (key) {
+ var path = this.path + key;
+ return new Uploader(path);
+ },
+
+ downloader: function (key) {
+ var path = this.path + key;
+ return new Downloader(path);
+ },
+
+ configure: function () {
+ // Determine whether folder to store images already exists
+ if (!fs.existsSync(this.path)) {
+ try {
+ // If not, try to create it
+ fs.mkdirSync(this.path);
+ } catch (error) {
+ // Log any errors and stop
+ return winston.error('creating image folder', error);
+ }
+ }
+
+ // All good
+ this.configured = true;
+ }
+
+};
+
+module.exports = ImagineFile;
@@ -0,0 +1,85 @@
+"use strict";
+
+var child = require('child_process');
+var events = require('events');
+var extend = require('obj-extend');
+var fs = require('fs');
+
+var Downloader = function (path) {
+ this.path = path;
+};
+
+Downloader.prototype = extend({}, events.EventEmitter.prototype, {
+
+ handleResponse: function () {
+ // Create a proxy stream
+ this.proxy = new events.EventEmitter();
+
+ // Get the mime type of the file
+ var that = this;
+ this.getMimeType(function (type) {
+ // Store the mime-type in the proxy headers
+ that.proxy.headers = { 'content-type': type };
+
+ // Stream out and emit the file data
+ that.emitData();
+ });
+ },
+
+ handleAbort: function () {
+ // Kill the child process, if appropriate
+ if (this.child) {
+ this.child.kill();
+ }
+
+ // Destroy the file read stream, if appropriate
+ if (this.stream) {
+ this.stream.destroy();
+ }
+ },
+
+ getMimeType: function (callback) {
+ // Get mime-type via linux command
+ var that = this;
+ var command = 'file --mime-type --brief ' + this.path;
+ this.child = child.exec(command, function (error, stdout, stderr) {
+ if (error) {
+ // Emit any errors
+ that.emit('error', {
+ statusCode: 404,
+ message: 'error retrieving file mime-type'
+ });
+ } else {
+ // Otherwise, return mime-type to callback
+ callback(stdout.slice(0, -1));
+ }
+ });
+ },
+
+ emitData: function () {
+ var that = this;
+ this.emit('response', this.proxy);
+ this.stream = fs.createReadStream(this.path);
+
+ // Emit any errors directly to this object
+ this.stream.on('error', function (error) {
+ that.emit('error', {
+ statusCode: 404,
+ message: 'error reading file from storage'
+ });
+ that.stream.removeAllListeners();
+ });
+
+ // Emit data/end to proxy
+ this.stream.on('data', function (chunk) {
+ that.proxy.emit('data', chunk);
+ });
+ this.stream.on('end', function () {
+ that.proxy.emit('end');
+ that.stream.removeAllListeners();
+ });
+ }
+
+});
+
+module.exports = Downloader;
@@ -0,0 +1,70 @@
+"use strict";
+
+var events = require('events');
+var extend = require('obj-extend');
+var fs = require('fs');
+
+var Uploader = function (path) {
+ this.path = path;
+};
+
+Uploader.prototype = extend({}, events.EventEmitter.prototype, {
+
+ handleResponse: function (response) {
+ this.response = response;
+
+ // Create the file
+ this.file = fs.openSync(this.path, 'w');
+
+ // Setup proxy stream and emit it
+ this.proxy = new events.EventEmitter();
+ this.proxy.headers = this.response.headers;
+ this.emit('response', this.proxy);
+
+ // Bind to the response stream
+ this.response.on('data', this.write.bind(this));
+ this.response.on('end', this.close.bind(this));
+ },
+
+ handleAbort: function () {
+ // Close out the file, if appropriate
+ if (this.file) {
+ this.close();
+ }
+ },
+
+ write: function (chunk) {
+ // Write to the file
+ var that = this;
+ fs.write(this.file, chunk, 0, chunk.length, null, function (err, w, buff) {
+ if (err) {
+ // Emit any errors
+ that.emit('error', {
+ statusCode: 500,
+ message: 'error writing to file'
+ });
+
+ // And close out the file
+ that.close();
+ } else {
+ // Otherwise, emit the chunks
+ that.proxy.emit('data', chunk);
+ }
+ });
+ },
+
+ close: function () {
+ // Clear the response listeners
+ this.response.removeAllListeners();
+
+ // Close out the file
+ var that = this;
+ fs.close(this.file, function () {
+ // Emit end
+ that.proxy.emit('end');
+ });
+ }
+
+});
+
+module.exports = Uploader;
@@ -0,0 +1,20 @@
+{
+ "name": "imagine-file",
+ "version": "0.1.0",
+ "description": "File storage for Imagine",
+ "homepage": "https://github.com/brewster/imagine-file",
+
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/brewster/imagine-file"
+ },
+
+ "main": "./lib/imagine-file",
+
+ "dependencies": {
+ "obj-extend": "~ 0.1.0",
+ "winston": "~ 0.5.11"
+ },
+
+ "license": "MIT"
+}

0 comments on commit 0d093dd

Please sign in to comment.