实现基本思路 : 后端返回文件流前端解析
以下代码有部分来自这个大佬
https://www.jianshu.com/p/56bfdae6f5c6
node后端
//node.js 文件操作对象
const fs = require('fs');
//node.js 路径操作对象
const path = require('path');
//egg.js Controller
const Controller = require('egg').Controller;
//故名思意 异步二进制 写入流
const awaitWriteStream = require('await-stream-ready').write;
//管道读入一个虫洞。
const sendToWormhole = require('stream-wormhole');
const md5 = require('md5');
module.exports = app => {
return class FileController extends app.Controller {
async upload (ctx) {
//egg-multipart 已经帮我们处理文件二进制对象
const stream = await ctx.getFileStream();
//新建一个文件名
const filename = md5(stream.filename) + path
.extname(stream.filename)
.toLocaleLowerCase();
//文件生成绝对路径
//当然这里这样市不行的,因为你还要判断一下是否存在文件路径
const target = path.join(this.config.baseDir, 'app/public/upload', filename);
//生成一个文件写入 文件流
const writeStream = fs.createWriteStream(target);
try {
//异步把文件流 写入
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
//如果出现错误,关闭管道
await sendToWormhole(stream);
throw err;
}
//将部分文件信息写入数据库
let docurl = '/app/public/upload/' + filename;
let docsize = stream.fields.docsize;
let username = stream.fields.username
let doctype = stream.fields.doctype
let doc=await ctx.model.Doc.create({
docurl,
doctype,
docname:stream.filename,
username,
docsize,
classid:stream.fields.selectedKey
});
ctx.success("上传成功!",doc);
}
如果有提示 excle('xls',xlsx) 等文件类型 读不出来 则在 config.default中 设置
multipart: {
fileSize: '50mb',
mode: 'stream',
fileExtensions: ['.xls', '.txt', '.xlsx', '.doc', 'docx'], // 扩展几种上传的文件格式
}
router文件
app.post('/admin/upload', app.controller.file.upload);
前端(react + antdRact)
前端上传文件 首先在接口处设置 contentType:'multipart/form-data'(不知道怎么写请百度,我项目中的请求是封装好的) ,以formdata的形式进行数据传输
代码:
<Upload onChange={this.loadonChange} showUploadList={false}>
<Button type="primary">上传</Button>
</Upload>
loadonChange = (info) => {
const { dispatch } = this.props
const { userinfo, selectedKey } = this.state
if (!selectedKey) {
message.error('请选择分类')
return
}
if (info.file.status !== 'uploading') {
}
if (info.file.status === 'done') {
let index = info.file.name.indexOf('.')
let result = info.file.name.substr(index + 1, info.file.name.length)
const formData = new FormData()
formData.append('file', info.file.originFileObj)
formData.append('username', userinfo.username)
formData.append('docsize', `${Math.ceil(info.file.size / 1024)}kb`)
formData.append('doctype', result)
formData.append('selectedKey', selectedKey)
dispatch({
type: 'file/fileLoad',
payload: formData,
})
}
}