'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); console.log(url); console.log(type); 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}${hz}`; const ffurl = `${saved.filePath}${resultname}`; if (!ffmpeg) throw new BusinessError(ErrorCode.SERVICE_FAULT, '转换失败'); 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;