UNPKG

@se7enwang/ghost-qn-store

Version:

Qiniu store for Ghost blog.

175 lines (149 loc) 4.23 kB
/** * Qiniu storage module for Ghost blog 1.x * @see https://docs.ghost.org/v1.0.0/docs/using-a-custom-storage-module */ 'use strict'; const path = require('path'); const fs = require('fs'); const urlParse = require('url').parse; const Promise = require('bluebird'); const moment = require('moment'); const qn = require('qn'); const StorageBase = require('ghost-storage-base'); const security = require('@tryghost/security'); const getHash = require('./lib/getHash'); const logPrefix = '[QiniuStore]'; class QiniuStore extends StorageBase { constructor(options) { super(options); this.options = options || {}; this.client = qn.create(this.options); } /** * Saves the image to storage * - image is the express image object * - returns a promise which ultimately returns the full url to the uploaded image * * @param file * @param targetDir * @returns {*} */ save(file, targetDir) { const client = this.client; const _this = this; return new Promise(function(resolve, reject) { _this.getFileKey(file).then((function(key) { client.upload(fs.createReadStream(file.path), { key: key }, function(err, result) { console.log(logPrefix, result); // console.log('[' + err.code + '] ' + err.name); err ? reject(err) : resolve(result.url); }); })); }); } /** * don't need it in Qiniu * @param filename * @param targetDir * @returns {*|bluebird} * @see https://support.qiniu.com/hc/kb/article/112817/ * TODO: if fileKey option set, should use key to check file whether exists */ exists(filename, targetDir) { return new Promise(function(resolve, reject) { resolve(false); }); } /* exists(filename) { return new Promise(function(resolve, reject) { // send key to get image info client.stat(filename, function(err, info) { if (info) { resolve(true); } else if (err && err.code === 612) { // File not exists resolve(false); } else { reject('Can\'t get file info.'); } }); }); }*/ // middleware for serving the files serve() { // a no-op, these are absolute URLs return function(req, res, next) { next(); }; } /** * Not implemented. * @description not really delete from Qiniu, may be implemented later * @param fileName * @param targetDir * @returns {*|bluebird} */ delete(fileName, targetDir) { // return Promise.reject('not implemented'); return new Promise(function(resolve, reject) { resolve(true); }); } /** * Reads bytes from Qiniu for a target image * * @param options */ read(options) { options = options || {}; const client = this.client; const key = urlParse(options.path).pathname.slice(1); return new Promise(function(resolve, reject) { client.download(key, function(err, content, res) { if (err) { return reject(err) } resolve(content); }); }); } getFileKey(file) { const keyOptions = this.options.fileKey; let fileKey = null; if (keyOptions) { const getValue = function(obj) { return typeof obj === 'function' ? obj() : obj; }; const ext = path.extname(file.name); let basename = path.basename(file.name, ext); let prefix = ''; let suffix = ''; let extname = ''; if (keyOptions.prefix) { prefix = moment().format(getValue(keyOptions.prefix)) .replace(/^\//, ''); } if (keyOptions.suffix) { suffix = getValue(keyOptions.suffix); } if (keyOptions.extname !== false) { extname = ext.toLowerCase(); } const contactKey = function(name) { return prefix + name + suffix + extname; }; if (keyOptions.hashAsBasename) { return getHash(file).then(function(hash) { return contactKey(hash); }); } else if (keyOptions.safeString) { basename = security.string.safe(basename); } fileKey = contactKey(basename); } return Promise.resolve(fileKey); } } module.exports = QiniuStore;