Authored by Targaryen

single-file-upload

1 'use strict'; 1 'use strict';
2 2
  3 +const CDNCONFIG = require('../../../config/cdn_config');
3 const _ = require('lodash'); 4 const _ = require('lodash');
4 const moment = require('moment'); 5 const moment = require('moment');
5 const Router = require('koa-router'); 6 const Router = require('koa-router');
  7 +const fs = require('fs');
  8 +const path = require('path');
6 const router = new Router(); 9 const router = new Router();
7 const FileApi = require('../../ci/file'); 10 const FileApi = require('../../ci/file');
8 -const CDNCONFIG = require('../../../config/cdn_config');  
9 -const qn = require('../../../lib/qiniu')(CDNCONFIG.feature); 11 +const qnFeature = require('../../../lib/qiniu')(CDNCONFIG.feature);
10 12
11 /** 13 /**
12 * 处理列表数据 14 * 处理列表数据
@@ -18,25 +20,18 @@ const _handleListItems = items => { @@ -18,25 +20,18 @@ const _handleListItems = items => {
18 let dateTime = _.parseInt(perFile.putTime.toString().substring(0, 13)); 20 let dateTime = _.parseInt(perFile.putTime.toString().substring(0, 13));
19 21
20 perFile.putTimeFormat = moment(dateTime).format('YYYY-MM-DD HH:mm'); 22 perFile.putTimeFormat = moment(dateTime).format('YYYY-MM-DD HH:mm');
21 - perFile.link = _.get(CDNCONFIG, 'feature.origin') + '/' + perFile.key; 23 + perFile.link = _.get(CDNCONFIG.feature, 'origin') + '/' + perFile.key;
22 }); 24 });
23 25
24 return items; 26 return items;
25 }; 27 };
26 28
27 -/**  
28 - * 校验是否是允许上传的文件包  
29 - */  
30 -const _verifyFiles = filesList => {  
31 - return true;  
32 -};  
33 -  
34 const file = { 29 const file = {
35 /** 30 /**
36 * 文件管理页面 31 * 文件管理页面
37 */ 32 */
38 page: async(ctx) => { 33 page: async(ctx) => {
39 - await ctx.render('/action/file_page', {domain: _.get(CDNCONFIG, 'feature.origin')}); 34 + await ctx.render('/action/file_page', {domain: _.get(CDNCONFIG.feature, 'origin')});
40 }, 35 },
41 36
42 /** 37 /**
@@ -68,7 +63,7 @@ const file = { @@ -68,7 +63,7 @@ const file = {
68 params.marker = ctx.query.marker; 63 params.marker = ctx.query.marker;
69 } 64 }
70 65
71 - let result = await qn.listAsync(params); 66 + let result = await qnFeature.listAsync(params);
72 let finalResult = { 67 let finalResult = {
73 items: _handleListItems(result.items) 68 items: _handleListItems(result.items)
74 }; 69 };
@@ -116,6 +111,66 @@ const file = { @@ -116,6 +111,66 @@ const file = {
116 message: '处理完毕', 111 message: '处理完毕',
117 data: {} 112 data: {}
118 }; 113 };
  114 + },
  115 +
  116 + /**
  117 + * 单文件上传页面
  118 + */
  119 + singleFile: async(ctx) => {
  120 + await ctx.render('/action/single_file_page', {domain: _.get(CDNCONFIG.main, 'origin')});
  121 + },
  122 +
  123 + /**
  124 + * 单文件上传处理
  125 + */
  126 + singleFileUpload: async(ctx, next) => {
  127 + if ('POST' !== ctx.method) return await next();
  128 +
  129 + let file = _.get(ctx, 'request.body._files.file');
  130 + let actPath = _.get(ctx, 'request.body.actPath');
  131 + let cover = _.get(ctx, 'request.body.cover') === 'yes'; // 是否覆盖
  132 + let filePath = path.join(actPath, _.get(file, 'name'));
  133 +
  134 + if (!file) {
  135 + return ctx.body = {
  136 + code: 400,
  137 + message: '没有接收到上传的文件'
  138 + };
  139 + }
  140 +
  141 + if (!actPath) {
  142 + return ctx.body = {
  143 + code: 400,
  144 + message: '请指定上传路径'
  145 + };
  146 + }
  147 +
  148 + let readable = fs.createReadStream(file.path);
  149 + let config = CDNCONFIG.main;
  150 +
  151 + if (cover) {
  152 + _.assign(CDNCONFIG.main, {
  153 + key: filePath
  154 + });
  155 + }
  156 +
  157 + let qnMain = require('../../../lib/qiniu')(config);
  158 + let upResult = await qnMain.uploadAsync(readable, {key: filePath});
  159 +
  160 + if (upResult && upResult.url) {
  161 + return ctx.body = {
  162 + code: 200,
  163 + message: '上传完毕',
  164 + data: {
  165 + url: upResult.url
  166 + }
  167 + };
  168 + } else {
  169 + return ctx.body = {
  170 + code: 400,
  171 + message: '上传失败,请重试'
  172 + };
  173 + }
119 } 174 }
120 } 175 }
121 176
@@ -123,5 +178,7 @@ router.get('/page', file.page); @@ -123,5 +178,7 @@ router.get('/page', file.page);
123 router.get('/listlogs', file.listLogs); 178 router.get('/listlogs', file.listLogs);
124 router.get('/listfiles', file.listFiles); 179 router.get('/listfiles', file.listFiles);
125 router.post('/upload', file.upload); 180 router.post('/upload', file.upload);
  181 +router.get('/single-file', file.singleFile);
  182 +router.post('/single-file-upload', file.singleFileUpload);
126 183
127 module.exports = router; 184 module.exports = router;
  1 +<div class="pageheader">
  2 + <div class="media">
  3 + <div class="pageicon pull-left">
  4 + <i class="fa fa-th-list"></i>
  5 + </div>
  6 + <div class="media-body">
  7 + <ul class="breadcrumb">
  8 + <li><a href=""><i class="glyphicon glyphicon-home"></i></a></li>
  9 + <li>静态资源</li>
  10 + </ul>
  11 + <h4>单文件上传</h4>
  12 + </div>
  13 + </div>
  14 + <!-- media -->
  15 +</div>
  16 +<!-- pageheader -->
  17 +<div class="contentpanel">
  18 + <div class="form">
  19 + <div class="form-group">
  20 + <label for=""></label>
  21 + <div class="input-group">
  22 + <span class="input-group-addon">{{domain}}/</span>
  23 + <input type="text" class="form-control" id="actPath" aria-describedby="basic-addon3" placeholder="请输入文件路径,例:20171030/v2.4.8">
  24 + </div>
  25 + </div>
  26 + <div class="form-group">
  27 + <label for="file">选择文件</label>
  28 + <input type="file" class="form-control" name="file" id="fileInput">
  29 + </div>
  30 + <input type="hidden" id="cover" name="cover">
  31 + <div class="form-group">
  32 + <button class="btn btn-default" id="upLoadBtn">上传</button>
  33 + </div>
  34 + </div>
  35 +</div>
  36 +
  37 +<script>
  38 + $('#upLoadBtn').on('click', function(){
  39 + var file = $('#fileInput').prop('files')[0];
  40 + var actPath = $('#actPath').val();
  41 + var formData = new FormData();
  42 + var cover = $('#cover').val();
  43 +
  44 + formData.append('file', file);
  45 + formData.append('actPath', actPath);
  46 + formData.append('cover', cover);
  47 +
  48 + $.ajax({
  49 + type: 'POST',
  50 + url: '/files/single-file-upload',
  51 + cache: false,
  52 + data: formData,
  53 + dataType: 'json',
  54 + processData: false,
  55 + contentType: false,
  56 + success: function(result) {
  57 + console.log(result);
  58 + }
  59 + });
  60 + });
  61 +</script>
@@ -65,6 +65,7 @@ @@ -65,6 +65,7 @@
65 <ul class="children"> 65 <ul class="children">
66 <li><a href="/check/list">代码检查</a></li> 66 <li><a href="/check/list">代码检查</a></li>
67 <li><a href="/files/page">活动上传</a></li> 67 <li><a href="/files/page">活动上传</a></li>
  68 + <li><a href="/files/single-file">单文件上传</a></li>
68 </ul> 69 </ul>
69 </li> 70 </li>
70 71
@@ -3,6 +3,13 @@ @@ -3,6 +3,13 @@
3 */ 3 */
4 4
5 const CDNCONFIG = { 5 const CDNCONFIG = {
  6 + main: {
  7 + accessKey: 'cY9B5ZgON_7McTS5zV5nTeRyQ98MOcVD7W4eGVbE',
  8 + secretKey: 'RduqgmK7cAtaQvdIa1ax_zzmMsnv9ac-Ka0uF6wG',
  9 + origin: 'http://cdn.yoho.cn',
  10 + bucket: 'yohocdn'
  11 + },
  12 +
6 feature: { 13 feature: {
7 origin: 'https://feature.yoho.cn', 14 origin: 'https://feature.yoho.cn',
8 bucket: 'yohogirlzine' 15 bucket: 'yohogirlzine'
@@ -6,22 +6,21 @@ @@ -6,22 +6,21 @@
6 6
7 'use strict'; 7 'use strict';
8 8
  9 +const CDNCONFIG = require('../config/cdn_config');
9 const qn = require('qn'); 10 const qn = require('qn');
10 const Promise = require('bluebird'); 11 const Promise = require('bluebird');
11 const _ = require('lodash'); 12 const _ = require('lodash');
12 13
13 -const config = {  
14 - accessKey: 'cY9B5ZgON_7McTS5zV5nTeRyQ98MOcVD7W4eGVbE',  
15 - secretKey: 'RduqgmK7cAtaQvdIa1ax_zzmMsnv9ac-Ka0uF6wG',  
16 - origin: 'http://cdn.yoho.cn',  
17 - bucket: 'yohocdn'  
18 -};  
19 -  
20 const _default = (params) => { 14 const _default = (params) => {
21 - let finalConfig = config; 15 + let finalConfig = CDNCONFIG.main;
22 16
23 if (params) { 17 if (params) {
24 _.assign(finalConfig, params); 18 _.assign(finalConfig, params);
  19 +
  20 + // 传 key 强制覆盖
  21 + if (params.key) {
  22 + finalConfig.bucket = params.bucket + ':' + params.key;
  23 + }
25 } 24 }
26 25
27 return Promise.promisifyAll( 26 return Promise.promisifyAll(
@@ -29,8 +28,11 @@ const _default = (params) => { @@ -29,8 +28,11 @@ const _default = (params) => {
29 ); 28 );
30 } 29 }
31 30
  31 +/**
  32 + * 兼容旧的强制覆盖逻辑,新功能开发弃用
  33 + */
32 _default.key = function(key) { 34 _default.key = function(key) {
33 - let _conifg = _.clone(config); 35 + let _conifg = _.clone(CDNCONFIG.main);
34 _conifg.bucket = _conifg.bucket + ":" + key; 36 _conifg.bucket = _conifg.bucket + ":" + key;
35 return Promise.promisifyAll(qn.create(_conifg)); 37 return Promise.promisifyAll(qn.create(_conifg));
36 }; 38 };