Egg中上传单文件与多文件

2020-11-26 10:46:34 浏览数 (1)

1. 单文件上传

1. 模板文件

代码语言:javascript复制
<!-- csrf为egg所提供的安全机制,需要在模板文件上绑定-->
<form action="/admin/upload/singleUpload?_csrf=<%=csrf%>" method="post" enctype="multipart/form-data">
    <ul>
        <li>
            图片名称:<input type="text" name="title" style="width:300px;"/>
        </li>

        <li>
            图片描述:<textarea name="description" id="" cols="60" rows="8" style="width:300px;"></textarea>
        </li>

        <!-- 上传文件必须在所有其他的 fields 后面,否则在拿到文件流时可能还获取不到 fields -->
        <li>
            图片封面:<input type="file" name="cover" style="width:300px;height:26px"/>
        </li>

        <li>
            <button type="submit" class="btn btn-primary">提交</button>
        </li>
    </ul>
</form>

2. 路由

代码语言:javascript复制
// router.js
'use strict';
module.exports = app => {
    const { router, controller } = app;
    router.post('/admin/upload/singleUpload',controller.admin.upload.singleUpload);
};

3. 控制器

代码语言:javascript复制
// app/controller/admin/upload.js

'use strict';

// npm install mz-modules --save
// 此模块解决上传超时卡死
// https://github.com/node-modules/mz-modules

const Pump = require('mz-modules/pump');

const Path = require('path');
const Fs = require('fs');

const Controller = require('egg').Controller;
// 上传控制器
class UploadController extends Controller {

    // 单文件上传
    async singleUpload() {
        // 获取表单提交的数据
        let stream = await this.ctx.getFileStream();
        // 防止上传空文件
        if (!stream.filename) {
            return;
        }
        // 文件名,实际项目中文件名要添加时间戳
        let filename = stream.filename.toLowerCase();

        // 上传的目录,注意upload目录要存在,实际项目中以云服务器地址为准,入库要替换地址符号
        let target = 'app/public/admin/upload/'   Path.basename(filename)
        // 创建写入流
        let writeStream = Fs.createWriteStream(target);

        // 上传超过时长会卡死
        // stream.pipe(writeStream);

        // 上传超过时长不会卡死
        await Pump(stream, writeStream);
        // 返回上传的信息
        this.ctx.body = {
            // 表单上传的图片
            url: target,
            // 表单的其它数据
            fields: stream.fields
        }
    }
   
    
}

module.exports = UploadController;

2. 多文件上传

1. 模板文件

代码语言:javascript复制
<!-- csrf为egg所提供的安全机制,需要在模板文件上绑定-->
<form action="/admin/upload/multiUpload?_csrf=<%=csrf%>" method="post" enctype="multipart/form-data">
    <ul>
        <input type="hidden" name="_csrf" value="<%=csrf%>">
        <li> 
            图片名称:<input type="text" name="title" style="width:300px;"/>
        </li>
        <li>
            图片描述:<textarea name="description" id="" cols="60" rows="8" style="width:300px;"></textarea>
        </li>
        <!-- 上传文件必须在所有其他的 fields 后面,否则在拿到文件流时可能还获取不到 fields -->
        <li>
            用户头像:<input type="file" name="avatar" style="width:300px;height:26px"/>
        </li>
        <li>
            素材封面:<input type="file" name="cover" style="width:300px;height:26px"/>
        </li>

        <li>
            <button type="submit" class="btn btn-primary">提交</button>
        </li>
    </ul>
</form>

2. 路由

代码语言:javascript复制
// router.js
'use strict';
module.exports = app => {
    const { router, controller } = app;
    router.post('/admin/upload/multiUpload',controller.admin.upload.multiUpload);

};

3. 控制器

代码语言:javascript复制
// app/controller/admin/upload.js

'use strict';

// npm install mz-modules --save
// 此模块解决上传超时卡死
// https://github.com/node-modules/mz-modules
const Pump = require('mz-modules/pump');

const Path = require('path');
const Fs = require('fs');

const Controller = require('egg').Controller;
// 上传控制器
class UploadController extends Controller {

    // 多文件上传
    async multiUpload() {
        // autoFields: true 表示除了文件的其它字段
        let parts = this.ctx.multipart({ autoFields: true });
        let files = [];
        let stream;
        // 循环获取数据流
        while ((stream = await parts()) != null) {
            if (!stream.filename) {
                // 多文件上传时,只能break,不能return
                break;
            }
            // 文件名,实际项目中文件名要添加时间戳
            let filename = stream.filename.toLowerCase();
            // 文件表单的name
            let fieldname = stream.fieldname;
            // 上传的目录,注意upload目录要存在,实际项目中以云服务器地址为准,入库要替换地址符号
            let target = 'app/public/admin/upload/'   Path.basename(filename);

            let writeStream = Fs.createWriteStream(target);
            await Pump(stream, writeStream);

            files.push({
                [fieldname]: target
            });
        }
        // 返回上传的信息
        this.ctx.body = {
            // 表单上传的文件
            files: files,
            // 表单的其它数据,注意放到循环后面,否则拿不到对应的字段
            fields: parts.field
        }

    }
}

module.exports = UploadController;

3. 上传配置

代码语言:javascript复制
// config/config.default.js

'use strict';
module.exports = appInfo => {
    const config = exports = {};
    config.keys = appInfo.name   '_1585450669767_9677';

    // 上传文件的配置
    // https://github.com/eggjs/egg-multipart
    config.multipart = {
        // 只允许上传的图片格式
        whitelist:['.png','.jpg','.jpeg'],
        // 文件允许大小
        fileSize: '50mb', 
    }

    // 配置两种模板引擎
    config.view = {
        mapping: {
            '.html': 'ejs',
            '.nj': 'nunjucks'
        }
    }

    return config

};

0 人点赞