|
@@ -1,146 +1,195 @@
|
|
|
-'use strict';
|
|
|
-
|
|
|
-const Controller = require('egg').Controller;
|
|
|
-const moment = require('moment');
|
|
|
-const { sep, extname } = require('path');
|
|
|
-const fs = require('fs');
|
|
|
-const awaitWriteStream = require('await-stream-ready').write;
|
|
|
-const sendToWormhole = require('stream-wormhole');
|
|
|
-const assert = require('assert');
|
|
|
-const wxstream = require('stream');
|
|
|
-const ffmpeg = require('fluent-ffmpeg');
|
|
|
-const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
|
-
|
|
|
-class FilesController extends Controller {
|
|
|
-
|
|
|
- async upload() {
|
|
|
- const { ctx, app } = this;
|
|
|
- const { appid, catalog, item } = ctx.params;
|
|
|
- assert(appid);
|
|
|
- const stream = await ctx.getFileStream();
|
|
|
- ctx.logger.debug(stream);
|
|
|
-
|
|
|
- const rootPath = `${app.config.cdn.repos_root_path}`;
|
|
|
- const rootUrl = `${app.config.cdn.repos_root_url}`;
|
|
|
- const dirs = [ appid ];
|
|
|
- if (catalog && catalog !== '_') {
|
|
|
- const subs = catalog.split('_');
|
|
|
- dirs.push(...subs);
|
|
|
- }
|
|
|
- const saved = await this.saveFile(rootPath, dirs, stream, item);
|
|
|
- const uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
- ctx.body = { errcode: 0, errmsg: 'ok', id: saved.id, name: saved.fileName, uri };
|
|
|
- }
|
|
|
-
|
|
|
- async saveFile(rootPath, dirs, stream, name) {
|
|
|
- const ctx = this.ctx;
|
|
|
- const ext = extname(stream.filename).toLowerCase();
|
|
|
- // TODO: 指定文件名或者按时间生成文件名
|
|
|
- // const name = moment().format('YYYYMMDDHHmmss');
|
|
|
- if (!name) name = moment().format('YYYYMMDDHHmmss');
|
|
|
-
|
|
|
- // TODO: 检查根路径是否存在,不存在则创建
|
|
|
- ctx.logger.debug('rootPath: ', rootPath);
|
|
|
- if (!fs.existsSync(rootPath)) {
|
|
|
- ctx.logger.debug('create dir: ', rootPath);
|
|
|
- fs.mkdirSync(rootPath);
|
|
|
- }
|
|
|
- // TODO: 检查分级目录是否存在,不存在则创建
|
|
|
- for (let i = 0; i < dirs.length; i++) {
|
|
|
- const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
|
|
|
- if (!fs.existsSync(p)) {
|
|
|
- fs.mkdirSync(p);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
|
|
|
- const fileName = `${name}${ext}`;
|
|
|
- const writeStream = fs.createWriteStream(filePath + fileName);
|
|
|
- try {
|
|
|
- await awaitWriteStream(stream.pipe(writeStream));
|
|
|
- } catch (err) {
|
|
|
- await sendToWormhole(stream);
|
|
|
- throw err;
|
|
|
- }
|
|
|
-
|
|
|
- return { filePath, fileName, id: name };
|
|
|
- }
|
|
|
-
|
|
|
- async wxupload() {
|
|
|
- const { serverid, type, appid } = this.ctx.request.body;
|
|
|
- assert(serverid, 'serverid不允许为空');
|
|
|
- assert(type, 'type不允许为空');
|
|
|
- const { ctx, app } = this;
|
|
|
- const url = app.config.wx.wxdown(appid, serverid);
|
|
|
- const file = await this.ctx.curl(url);
|
|
|
- console.log(url);
|
|
|
- const stream = new wxstream.PassThrough();
|
|
|
- stream.end(file.data);
|
|
|
- const rootPath = `${app.config.cdn.repos_root_path}`;
|
|
|
- const rootUrl = `${app.config.cdn.repos_root_url}`;
|
|
|
- let uri;
|
|
|
- // 判断类型 0、图片 1、音频 2、视频
|
|
|
- if (type === '0') {
|
|
|
- const dirs = [ 'wximage' ];
|
|
|
- const saved = await this.wxsaveFile(rootPath, dirs, stream, '.jpg');
|
|
|
- uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
- } else if (type === '1') {
|
|
|
- const dirs = [ 'wxadio' ];
|
|
|
- const saved = await this.wxsaveFile(rootPath, dirs, stream, '.amr');
|
|
|
- // 音频时如果需要使用转码,以下调用ffmpeg进行转码处理
|
|
|
- // const hz = '.mp3';
|
|
|
- const resultname = `${saved.id}.amr`;
|
|
|
- // const ffurl = `${saved.filePath}${resultname}`;
|
|
|
- // if (!ffmpeg) throw new BusinessError(ErrorCode.SERVICE_FAULT, '转换失败');
|
|
|
- // new ffmpeg({ source: `${saved.filePath}${saved.fileName}` })
|
|
|
- // .saveToFile(ffurl, function(retcode, error) {
|
|
|
- // })
|
|
|
- // .on('end', function() {
|
|
|
- // // 在这里处理完成后的结果
|
|
|
- // console.log('Finished processing');
|
|
|
- // });
|
|
|
- uri = `${rootUrl}/${dirs.join('/')}/${resultname}`;
|
|
|
- } else if (type === '2') {
|
|
|
- const dirs = [ 'wxvideo' ];
|
|
|
- const saved = await this.wxsaveFile(rootPath, dirs, stream, '');
|
|
|
- uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
- }
|
|
|
- ctx.body = { errcode: 0, errmsg: 'ok', uri };
|
|
|
- }
|
|
|
-
|
|
|
- async wxsaveFile(rootPath, dirs, stream, ext) {
|
|
|
- const ctx = this.ctx;
|
|
|
- // TODO: 指定文件名或者按时间生成文件名
|
|
|
- const name = moment().format('YYYYMMDDHHmmss');
|
|
|
-
|
|
|
- // TODO: 检查根路径是否存在,不存在则创建
|
|
|
- ctx.logger.debug('rootPath: ', rootPath);
|
|
|
- if (!fs.existsSync(rootPath)) {
|
|
|
- ctx.logger.debug('create dir: ', rootPath);
|
|
|
- fs.mkdirSync(rootPath);
|
|
|
- }
|
|
|
- // TODO: 检查分级目录是否存在,不存在则创建
|
|
|
- for (let i = 0; i < dirs.length; i++) {
|
|
|
- const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
|
|
|
- if (!fs.existsSync(p)) {
|
|
|
- fs.mkdirSync(p);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
|
|
|
- const fileName = `${name}${ext}`;
|
|
|
- console.log(filePath + fileName);
|
|
|
- const writeStream = fs.createWriteStream(filePath + fileName);
|
|
|
- try {
|
|
|
- await awaitWriteStream(stream.pipe(writeStream));
|
|
|
- } catch (err) {
|
|
|
- await sendToWormhole(stream);
|
|
|
- throw err;
|
|
|
- }
|
|
|
-
|
|
|
- return { filePath, fileName, id: name };
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-module.exports = FilesController;
|
|
|
+'use strict';
|
|
|
+
|
|
|
+const Controller = require('egg').Controller;
|
|
|
+const moment = require('moment');
|
|
|
+const { sep, extname } = require('path');
|
|
|
+const fs = require('fs');
|
|
|
+const awaitWriteStream = require('await-stream-ready').write;
|
|
|
+const sendToWormhole = require('stream-wormhole');
|
|
|
+const assert = require('assert');
|
|
|
+const wxstream = require('stream');
|
|
|
+const ffmpeg = require('fluent-ffmpeg');
|
|
|
+const { BusinessError, ErrorCode } = require('naf-core').Error;
|
|
|
+
|
|
|
+class FilesController extends Controller {
|
|
|
+
|
|
|
+ async upload() {
|
|
|
+ const { ctx, app } = this;
|
|
|
+ const { appid, catalog, item } = ctx.params;
|
|
|
+ assert(appid);
|
|
|
+ const stream = await ctx.getFileStream();
|
|
|
+ ctx.logger.debug(stream);
|
|
|
+
|
|
|
+ const rootPath = `${app.config.cdn.repos_root_path}`;
|
|
|
+ const rootUrl = `${app.config.cdn.repos_root_url}`;
|
|
|
+ const dirs = [ appid ];
|
|
|
+ if (catalog && catalog !== '_') {
|
|
|
+ const subs = catalog.split('_');
|
|
|
+ dirs.push(...subs);
|
|
|
+ }
|
|
|
+ const saved = await this.saveFile(rootPath, dirs, stream, item);
|
|
|
+ const uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
+ ctx.body = { errcode: 0, errmsg: 'ok', id: saved.id, name: saved.fileName, uri };
|
|
|
+ }
|
|
|
+
|
|
|
+ async saveFile(rootPath, dirs, stream, name) {
|
|
|
+ const ctx = this.ctx;
|
|
|
+ const ext = extname(stream.filename).toLowerCase();
|
|
|
+ // TODO: 指定文件名或者按时间生成文件名
|
|
|
+ // const name = moment().format('YYYYMMDDHHmmss');
|
|
|
+ if (!name) name = moment().format('YYYYMMDDHHmmss');
|
|
|
+
|
|
|
+ // TODO: 检查根路径是否存在,不存在则创建
|
|
|
+ ctx.logger.debug('rootPath: ', rootPath);
|
|
|
+ if (!fs.existsSync(rootPath)) {
|
|
|
+ ctx.logger.debug('create dir: ', rootPath);
|
|
|
+ fs.mkdirSync(rootPath);
|
|
|
+ }
|
|
|
+ // TODO: 检查分级目录是否存在,不存在则创建
|
|
|
+ for (let i = 0; i < dirs.length; i++) {
|
|
|
+ const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
|
|
|
+ if (!fs.existsSync(p)) {
|
|
|
+ fs.mkdirSync(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
|
|
|
+ const fileName = `${name}${ext}`;
|
|
|
+ const writeStream = fs.createWriteStream(filePath + fileName);
|
|
|
+ try {
|
|
|
+ await awaitWriteStream(stream.pipe(writeStream));
|
|
|
+ } catch (err) {
|
|
|
+ await sendToWormhole(stream);
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return { filePath, fileName, id: name };
|
|
|
+ }
|
|
|
+
|
|
|
+ async wxupload() {
|
|
|
+ const { serverid, type, appid } = this.ctx.request.body;
|
|
|
+ assert(serverid, 'serverid不允许为空');
|
|
|
+ assert(type, 'type不允许为空');
|
|
|
+ const { ctx, app } = this;
|
|
|
+ const url = app.config.wx.wxdown(appid, serverid);
|
|
|
+ const file = await this.ctx.curl(url);
|
|
|
+ const stream = new wxstream.PassThrough();
|
|
|
+ stream.end(file.data);
|
|
|
+ const rootPath = `${app.config.cdn.repos_root_path}`;
|
|
|
+ const rootUrl = `${app.config.cdn.repos_root_url}`;
|
|
|
+ let uri;
|
|
|
+ // 判断类型 0、图片 1、音频 2、视频
|
|
|
+ if (type === '0') {
|
|
|
+ const dirs = [ 'wximage' ];
|
|
|
+ const saved = await this.wxsaveFile(rootPath, dirs, stream, '.jpg');
|
|
|
+ uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
+ } else if (type === '1') {
|
|
|
+ const dirs = [ 'wxadio' ];
|
|
|
+ const saved = await this.wxsaveFile(rootPath, dirs, stream, '.amr');
|
|
|
+ // 音频时如果需要使用转码,以下调用ffmpeg进行转码处理
|
|
|
+ // const hz = '.mp3';
|
|
|
+ const resultname = `${saved.id}.amr`;
|
|
|
+ // const ffurl = `${saved.filePath}${resultname}`;
|
|
|
+ // if (!ffmpeg) throw new BusinessError(ErrorCode.SERVICE_FAULT, '转换失败');
|
|
|
+ // new ffmpeg({ source: `${saved.filePath}${saved.fileName}` })
|
|
|
+ // .saveToFile(ffurl, function(retcode, error) {
|
|
|
+ // })
|
|
|
+ // .on('end', function() {
|
|
|
+ // // 在这里处理完成后的结果
|
|
|
+ // console.log('Finished processing');
|
|
|
+ // });
|
|
|
+ uri = `${rootUrl}/${dirs.join('/')}/${resultname}`;
|
|
|
+ } else if (type === '2') {
|
|
|
+ const dirs = [ 'wxvideo' ];
|
|
|
+ const saved = await this.wxsaveFile(rootPath, dirs, stream, '');
|
|
|
+ uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
|
|
|
+ }
|
|
|
+ ctx.body = { errcode: 0, errmsg: 'ok', uri };
|
|
|
+ }
|
|
|
+
|
|
|
+ async wxsaveFile(rootPath, dirs, stream, ext) {
|
|
|
+ const ctx = this.ctx;
|
|
|
+ // TODO: 指定文件名或者按时间生成文件名
|
|
|
+ const name = moment().format('YYYYMMDDHHmmss');
|
|
|
+
|
|
|
+ // TODO: 检查根路径是否存在,不存在则创建
|
|
|
+ ctx.logger.debug('rootPath: ', rootPath);
|
|
|
+ if (!fs.existsSync(rootPath)) {
|
|
|
+ ctx.logger.debug('create dir: ', rootPath);
|
|
|
+ fs.mkdirSync(rootPath);
|
|
|
+ }
|
|
|
+ // TODO: 检查分级目录是否存在,不存在则创建
|
|
|
+ for (let i = 0; i < dirs.length; i++) {
|
|
|
+ const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
|
|
|
+ if (!fs.existsSync(p)) {
|
|
|
+ fs.mkdirSync(p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
|
|
|
+ const fileName = `${name}${ext}`;
|
|
|
+ const writeStream = fs.createWriteStream(filePath + fileName);
|
|
|
+ try {
|
|
|
+ await awaitWriteStream(stream.pipe(writeStream));
|
|
|
+ } catch (err) {
|
|
|
+ await sendToWormhole(stream);
|
|
|
+ throw err;
|
|
|
+ }
|
|
|
+
|
|
|
+ return { filePath, fileName, id: name };
|
|
|
+ }
|
|
|
+
|
|
|
+ async serverUpload() {
|
|
|
+ const { ctx, app } = this;
|
|
|
+ const body = ctx.request.body;
|
|
|
+ const { name, uri, extension, code } = body;
|
|
|
+ const path = uri;
|
|
|
+ if (!path) {
|
|
|
+ return this.getErrorReturn('缺少文件存储路径');
|
|
|
+ }
|
|
|
+ const rootPath = `${app.config.cdn.repos_root_path}`;
|
|
|
+ const rootUrl = `${app.config.cdn.repos_root_url}`;
|
|
|
+ if (!fs.existsSync(rootPath)) {
|
|
|
+ ctx.logger.debug('create dir: ', rootPath);
|
|
|
+ fs.mkdirSync(rootPath);
|
|
|
+ }
|
|
|
+ const dirs = path.split('/');
|
|
|
+ dirs.pop();
|
|
|
+ // 检查路径是否存在,不存在就创建
|
|
|
+ let realPath = rootPath;
|
|
|
+ const realPathArray = [];
|
|
|
+ for (const p of dirs) {
|
|
|
+ const children = p.split('_');
|
|
|
+ for (const c of children) {
|
|
|
+ realPath = `${realPath}${sep}${c}`;
|
|
|
+ if (!fs.existsSync(realPath)) {
|
|
|
+ fs.mkdirSync(realPath);
|
|
|
+ }
|
|
|
+ realPathArray.push(c);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const filePath = `${rootUrl}/${realPathArray.join('/')}`;
|
|
|
+ const fileName = `${name || new Date().getTime()}.${extension}`;
|
|
|
+ try {
|
|
|
+ const base64Data = code.replace(/^data:image\/\w+;base64,/, '');
|
|
|
+ const dataBuffer = Buffer(base64Data, 'base64');
|
|
|
+ await fs.writeFileSync(`${realPath}${sep}${fileName}`, Buffer(dataBuffer, 'base64'));
|
|
|
+ } catch (error) {
|
|
|
+ throw error;
|
|
|
+ }
|
|
|
+
|
|
|
+ const returnUri = `${filePath}/${fileName}`;
|
|
|
+ this.ctx.body = this.getSuccessReturn({ uri: returnUri, id: fileName });
|
|
|
+ }
|
|
|
+
|
|
|
+ getErrorReturn(message) {
|
|
|
+ return { errcode: -1, errmsg: message || '程序发生错误' };
|
|
|
+ }
|
|
|
+
|
|
|
+ getSuccessReturn(data) {
|
|
|
+ return { errcode: 0, errmsg: 'ok', data };
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+module.exports = FilesController;
|