files.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. 'use strict';
  2. const Controller = require('egg').Controller;
  3. const moment = require('moment');
  4. const { sep, extname } = require('path');
  5. const fs = require('fs');
  6. const awaitWriteStream = require('await-stream-ready').write;
  7. const sendToWormhole = require('stream-wormhole');
  8. const assert = require('assert');
  9. const wxstream = require('stream');
  10. const ffmpeg = require('fluent-ffmpeg');
  11. class FilesController extends Controller {
  12. async upload() {
  13. const { ctx, app } = this;
  14. const { appid, catalog, item } = ctx.params;
  15. assert(appid);
  16. const stream = await ctx.getFileStream();
  17. ctx.logger.debug(stream);
  18. const rootPath = `${app.config.cdn.repos_root_path}`;
  19. const rootUrl = `${app.config.cdn.repos_root_url}`;
  20. const dirs = [ appid ];
  21. if (catalog && catalog !== '_') {
  22. const subs = catalog.split('_');
  23. dirs.push(...subs);
  24. }
  25. const saved = await this.saveFile(rootPath, dirs, stream, item);
  26. const uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
  27. ctx.body = { errcode: 0, errmsg: 'ok', id: saved.id, name: saved.fileName, uri };
  28. }
  29. async saveFile(rootPath, dirs, stream, name) {
  30. const ctx = this.ctx;
  31. const ext = extname(stream.filename).toLowerCase();
  32. // TODO: 指定文件名或者按时间生成文件名
  33. // const name = moment().format('YYYYMMDDHHmmss');
  34. if (!name) name = moment().format('YYYYMMDDHHmmss');
  35. // TODO: 检查根路径是否存在,不存在则创建
  36. ctx.logger.debug('rootPath: ', rootPath);
  37. if (!fs.existsSync(rootPath)) {
  38. ctx.logger.debug('create dir: ', rootPath);
  39. fs.mkdirSync(rootPath);
  40. }
  41. // TODO: 检查分级目录是否存在,不存在则创建
  42. for (let i = 0; i < dirs.length; i++) {
  43. const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
  44. if (!fs.existsSync(p)) {
  45. fs.mkdirSync(p);
  46. }
  47. }
  48. const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
  49. const fileName = `${name}${ext}`;
  50. const writeStream = fs.createWriteStream(filePath + fileName);
  51. try {
  52. await awaitWriteStream(stream.pipe(writeStream));
  53. } catch (err) {
  54. await sendToWormhole(stream);
  55. throw err;
  56. }
  57. return { filePath, fileName, id: name };
  58. }
  59. async wxupload() {
  60. const { serverid, type } = this.ctx.request.body;
  61. assert(serverid, 'serverid不允许为空');
  62. assert(type, 'type不允许为空');
  63. const { ctx, app } = this;
  64. const url = app.config.wx.wxdown + serverid;
  65. console.log(url);
  66. console.log(type);
  67. const file = await this.ctx.curl(url);
  68. const stream = new wxstream.PassThrough();
  69. stream.end(file.data);
  70. const rootPath = `${app.config.cdn.repos_root_path}`;
  71. const rootUrl = `${app.config.cdn.repos_root_url}`;
  72. let uri;
  73. // 判断类型 0、图片 1、音频 2、视频
  74. if (type === '0') {
  75. const dirs = [ 'wximage' ];
  76. const saved = await this.wxsaveFile(rootPath, dirs, stream, '.jpg');
  77. uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
  78. } else if (type === '1') {
  79. const dirs = [ 'wxadio' ];
  80. const saved = await this.wxsaveFile(rootPath, dirs, stream, '.amr');
  81. // 音频时如果需要使用转码,以下调用ffmpeg进行转码处理
  82. const hz = '.mp3';
  83. const resultname = `${saved.id}${hz}`;
  84. const ffurl = `${saved.filePath}${resultname}`;
  85. new ffmpeg({ source: `${saved.filePath}${saved.fileName}` })
  86. .saveToFile(ffurl, function(retcode, error) {
  87. })
  88. .on('end', function() {
  89. // 在这里处理完成后的结果
  90. console.log('Finished processing');
  91. });
  92. uri = `${rootUrl}/${dirs.join('/')}/${resultname}`;
  93. } else if (type === '2') {
  94. const dirs = [ 'wxvideo' ];
  95. const saved = await this.wxsaveFile(rootPath, dirs, stream, '');
  96. uri = `${rootUrl}/${dirs.join('/')}/${saved.fileName}`;
  97. }
  98. ctx.body = { errcode: 0, errmsg: 'ok', uri };
  99. }
  100. async wxsaveFile(rootPath, dirs, stream, ext) {
  101. const ctx = this.ctx;
  102. // TODO: 指定文件名或者按时间生成文件名
  103. const name = moment().format('YYYYMMDDHHmmss');
  104. // TODO: 检查根路径是否存在,不存在则创建
  105. ctx.logger.debug('rootPath: ', rootPath);
  106. if (!fs.existsSync(rootPath)) {
  107. ctx.logger.debug('create dir: ', rootPath);
  108. fs.mkdirSync(rootPath);
  109. }
  110. // TODO: 检查分级目录是否存在,不存在则创建
  111. for (let i = 0; i < dirs.length; i++) {
  112. const p = `${rootPath}${sep}${dirs.slice(0, i + 1).join(sep)}`;
  113. if (!fs.existsSync(p)) {
  114. fs.mkdirSync(p);
  115. }
  116. }
  117. const filePath = `${rootPath}${sep}${dirs.join(sep)}${sep}`;
  118. const fileName = `${name}${ext}`;
  119. console.log(filePath + fileName);
  120. const writeStream = fs.createWriteStream(filePath + fileName);
  121. try {
  122. await awaitWriteStream(stream.pipe(writeStream));
  123. } catch (err) {
  124. await sendToWormhole(stream);
  125. throw err;
  126. }
  127. return { filePath, fileName, id: name };
  128. }
  129. }
  130. module.exports = FilesController;