From 4804a2031b8024690b74492733b73490bd61b651 Mon Sep 17 00:00:00 2001 From: dengtongyu Date: Wed, 25 Nov 2020 16:20:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/files.js | 49 +++++++++++++++++++++++++++++++++++++++++ app/router.js | 1 + app/router/files.js | 7 ++++++ app/util/tool.js | 46 ++++++++++++++++++++++++++++++++++++++ config/config.local.js | 23 +++++++++++++++++++ config/config.prod.js | 21 ++++++++++++++++++ package.json | 4 ++-- 7 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 app/controller/files.js create mode 100644 app/router/files.js create mode 100644 app/util/tool.js create mode 100644 config/config.local.js create mode 100644 config/config.prod.js diff --git a/app/controller/files.js b/app/controller/files.js new file mode 100644 index 0000000..d1f65e4 --- /dev/null +++ b/app/controller/files.js @@ -0,0 +1,49 @@ +'use strict'; + +const Controller = require('egg').Controller; +const fs = require('fs'); +const { COPYFILE_EXCL } = fs.constants; +const respFormat = require('../util/respFormat'); +const { randomString, getSuffix, getFilePath } = require('../util/tool'); + +class FilesController extends Controller { + async upload() { + const { ctx } = this; + console.log(ctx.request.body); + console.log('got %d files', ctx.request.files.length); + + try { + + const filesResult = []; + const rootPath = this.config.uploadBasePath; + // 遍历处理多个文件 + for (const file of ctx.request.files) { + console.log('field: ' + file.fieldname); + console.log('filename: ' + file.filename); + console.log('encoding: ' + file.encoding); + console.log('mime: ' + file.mime); + console.log('tmp filepath: ' + file.filepath); + const type = ctx.request.body.type; + const suff = getSuffix(file.filename); + const newFileName = randomString(16) + suff; + const filePath = rootPath + getFilePath(type); + if (!fs.existsSync()) fs.mkdirSync(filePath); + const targetPath = filePath + newFileName; + await fs.copyFileSync(file.filepath, targetPath, COPYFILE_EXCL); + const item = { + filename: file.filename, + url: `https://image.dengtongyu.com${targetPath}`, + }; + filesResult.push(item); + } + + ctx.body = respFormat({ data: filesResult }); + await ctx.cleanupRequestFiles(); + } finally { + // 需要删除临时文件 + await ctx.cleanupRequestFiles(); + } + } +} + +module.exports = FilesController; diff --git a/app/router.js b/app/router.js index 6d44c9a..b710831 100644 --- a/app/router.js +++ b/app/router.js @@ -9,4 +9,5 @@ module.exports = app => { require('./router/music')(app); require('./router/nsfw')(app); + require('./router/files')(app); }; diff --git a/app/router/files.js b/app/router/files.js new file mode 100644 index 0000000..ae8ff03 --- /dev/null +++ b/app/router/files.js @@ -0,0 +1,7 @@ +'use strict'; + +module.exports = app => { + const { router, controller } = app; + + router.post('/files/upload', controller.files.upload); +}; diff --git a/app/util/tool.js b/app/util/tool.js new file mode 100644 index 0000000..4d99be1 --- /dev/null +++ b/app/util/tool.js @@ -0,0 +1,46 @@ +'use strict'; + +// 随机长度字符串 +const randomString = len => { + len = len || 10; + const chars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const maxPos = chars.length; + let str = ''; + for (let i = 0; i < len; i++) { + str += chars.charAt(Math.floor(Math.random() * maxPos)); + } + return str; +}; + +const getSuffix = fileName => { + const arr = fileName.split('.'); + let suffix = ''; + if (arr.length >= 2) { + suffix = arr[arr.length - 1]; + } + if (suffix) suffix = `.${suffix}`; + return suffix; +}; + +const getFilePath = type => { + const now = new Date(); + const fullYears = now.getFullYear(); + const Month = now.getMonth(); + let typeStr = ''; + switch (type) { + case 'blog': + typeStr = 'blog'; + break; + default: + typeStr = 'media'; + break; + } + const path = `${typeStr}/${fullYears}/${Month}/`; + return path; +}; + +module.exports = { + randomString, + getSuffix, + getFilePath, +}; diff --git a/config/config.local.js b/config/config.local.js new file mode 100644 index 0000000..0c4eb95 --- /dev/null +++ b/config/config.local.js @@ -0,0 +1,23 @@ +/* eslint valid-jsdoc: "off" */ + +'use strict'; + +const path = require('path'); + +/** + * @param {Egg.EggAppInfo} appInfo app info + */ +// eslint-disable-next-line no-unused-vars +module.exports = appInfo => { + /** + * built-in config + * @type {Egg.EggAppConfig} + **/ + const config = exports = {}; + + config.uploadBasePath = path.join(__dirname, '../'); + + return { + ...config, + }; +}; diff --git a/config/config.prod.js b/config/config.prod.js new file mode 100644 index 0000000..68b0cb9 --- /dev/null +++ b/config/config.prod.js @@ -0,0 +1,21 @@ +/* eslint valid-jsdoc: "off" */ + +'use strict'; + +/** + * @param {Egg.EggAppInfo} appInfo app info + */ +// eslint-disable-next-line no-unused-vars +module.exports = appInfo => { + /** + * built-in config + * @type {Egg.EggAppConfig} + **/ + const config = exports = {}; + + config.uploadBasePath = '/webroot/image/'; + + return { + ...config, + }; +}; diff --git a/package.json b/package.json index b6faef4..ba04d12 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,9 @@ "node": ">=10.0.0" }, "scripts": { - "start": "egg-scripts start --daemon --title=egg-server-api-service", + "start": "EGG_SERVER_ENV=prod egg-scripts start --daemon --title=egg-server-api-service", "stop": "egg-scripts stop --title=egg-server-api-service", - "dev": "egg-bin dev", + "dev": "EGG_SERVER_ENV=local egg-bin dev", "debug": "egg-bin debug", "test": "npm run lint -- --fix && npm run test-local", "test-local": "egg-bin test",