From e97d59cc5806786662a0f3ae5f78162c83875647 Mon Sep 17 00:00:00 2001 From: kirrg001 Date: Wed, 9 Nov 2016 09:17:27 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=20add=20read=20method=20to=20local?= =?UTF-8?q?=20file=20storage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs #7688 - add a read method to our local file storage - reads the bytes of a target image - breaking change to storage adapters --- core/server/storage/base.js | 2 +- core/server/storage/local-file-store.js | 34 +++++++++++++++--- core/test/unit/storage/index_spec.js | 2 ++ .../unit/storage/local-file-store_spec.js | 36 +++++++++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/core/server/storage/base.js b/core/server/storage/base.js index 04aba1172b..2a6b7b252a 100644 --- a/core/server/storage/base.js +++ b/core/server/storage/base.js @@ -3,7 +3,7 @@ var moment = require('moment'), function StorageBase() { Object.defineProperty(this, 'requiredFns', { - value: ['exists', 'save', 'serve', 'delete'], + value: ['exists', 'save', 'serve', 'delete', 'read'], writable: false }); } diff --git a/core/server/storage/local-file-store.js b/core/server/storage/local-file-store.js index 0ce4b4327e..c03af6075a 100644 --- a/core/server/storage/local-file-store.js +++ b/core/server/storage/local-file-store.js @@ -24,7 +24,7 @@ util.inherits(LocalFileStore, BaseStore); // Saves the image to storage (the file system) // - image is the express image object // - returns a promise which ultimately returns the full url to the uploaded image -LocalFileStore.prototype.save = function (image, targetDir) { +LocalFileStore.prototype.save = function save(image, targetDir) { targetDir = targetDir || this.getTargetDir(config.getContentPath('images')); var targetFilename; @@ -49,7 +49,7 @@ LocalFileStore.prototype.save = function (image, targetDir) { }); }; -LocalFileStore.prototype.exists = function (filename) { +LocalFileStore.prototype.exists = function exists(filename) { return new Promise(function (resolve) { fs.stat(filename, function (err) { var exists = !err; @@ -59,7 +59,7 @@ LocalFileStore.prototype.exists = function (filename) { }; // middleware for serving the files -LocalFileStore.prototype.serve = function (options) { +LocalFileStore.prototype.serve = function serve(options) { options = options || {}; // CASE: serve themes @@ -117,11 +117,37 @@ LocalFileStore.prototype.serve = function (options) { } }; -LocalFileStore.prototype.delete = function (fileName, targetDir) { +LocalFileStore.prototype.delete = function deleteFile(fileName, targetDir) { targetDir = targetDir || this.getTargetDir(config.getContentPath('images')); var pathToDelete = path.join(targetDir, fileName); return remove(pathToDelete); }; +/** + * Reads bytes from disk for a target image + * path: path of target image (without content path!) + */ +LocalFileStore.prototype.read = function read(options) { + options = options || {}; + + // remove trailing slashes + options.path = (options.path || '').replace(/\/$|\\$/, ''); + + var targetPath = path.join(config.getContentPath('images'), options.path); + + return new Promise(function (resolve, reject) { + fs.readFile(targetPath, function (err, bytes) { + if (err) { + return reject(new errors.GhostError({ + err: err, + message: 'Could not read image: ' + targetPath + })); + } + + resolve(bytes); + }); + }); +}; + module.exports = LocalFileStore; diff --git a/core/test/unit/storage/index_spec.js b/core/test/unit/storage/index_spec.js index 5deaa84770..4ed305fdbe 100644 --- a/core/test/unit/storage/index_spec.js +++ b/core/test/unit/storage/index_spec.js @@ -67,6 +67,7 @@ describe('storage: index_spec', function () { 'AnotherAdapter.prototype.save = function (){};' + 'AnotherAdapter.prototype.serve = function (){};' + 'AnotherAdapter.prototype.delete = function (){};' + + 'AnotherAdapter.prototype.read = function (){};' + 'module.exports = AnotherAdapter', chosenStorage; fs.writeFileSync(scope.adapter, jsFile); @@ -103,6 +104,7 @@ describe('storage: index_spec', function () { 'AnotherAdapter.prototype.save = function (){};' + 'AnotherAdapter.prototype.serve = function (){};' + 'AnotherAdapter.prototype.delete = function (){};' + + 'AnotherAdapter.prototype.read = function (){};' + 'module.exports = AnotherAdapter', adapter; fs.writeFileSync(scope.adapter, jsFile); diff --git a/core/test/unit/storage/local-file-store_spec.js b/core/test/unit/storage/local-file-store_spec.js index ad069c8552..bdc250c1ab 100644 --- a/core/test/unit/storage/local-file-store_spec.js +++ b/core/test/unit/storage/local-file-store_spec.js @@ -3,6 +3,7 @@ var fs = require('fs-extra'), path = require('path'), should = require('should'), sinon = require('sinon'), + errors = require('../../../server/errors'), LocalFileStore = require('../../../server/storage/local-file-store'), localFileStore, @@ -148,6 +149,41 @@ describe('Local File System Storage', function () { }).catch(done); }); + describe('read image', function () { + beforeEach(function () { + // we have some example images in our test utils folder + configUtils.set('paths:contentPath', path.join(__dirname, '../../utils/fixtures')); + }); + + it('success', function (done) { + localFileStore.read({path: 'ghost-logo.png'}) + .then(function (bytes) { + bytes.length.should.eql(8638); + done(); + }); + }); + + it('success', function (done) { + localFileStore.read({path: '/ghost-logo.png/'}) + .then(function (bytes) { + bytes.length.should.eql(8638); + done(); + }); + }); + + it('image does not exist', function (done) { + localFileStore.read({path: 'does-not-exist.png'}) + .then(function () { + done(new Error('image should not exist')); + }) + .catch(function (err) { + (err instanceof errors.GhostError).should.eql(true); + err.code.should.eql('ENOENT'); + done(); + }); + }); + }); + describe('validate extentions', function () { it('name contains a .\d as extension', function (done) { localFileStore.save({