背景:点击【浏览】按钮选择一个文件,将文件名获取到展示在页面上,用户可以随意更改选择的文件,点击【上传文件】按钮将已上传的文件上送给后台
入坑1:根据以上背景需求,使用ant design upload上传组件,该组件的原理默认是选择文件即上传,当然为了满足项目需求,可以在上传的beforeUpload 函数里给return false,只用于拦截上传行为,不会阻止文件进入上传列表(原因)。如果需要阻止列表展现,可以参照此例配合 onChange 进行实现。看一下图例
在上述图中beforeUpload中禁止默认上传,先存一下上传的文件,在点击最后上传的按钮时,在将文件上送给后端,图例如下:
上图框①中是将文件进行二进制转化,必须要这样转换一下,框②是因为上送给后台是,前端发送过去的请求头是”Content-Type:application/json; charset=utf-8 ,在后端就会报这样的错”Current request is not a multipart request“意思就是说前端猿媛上送的不是一个文件格式,后台拦截了,于是乎,我在reqwest请求中加上 contentType:'multipart/form-data; boundary=----WebKitFormBoundaryjktt63FyovoiTw9T',或者 contentType:'multipart/form-data',尝试上送,依然在请求头request header中显示Content-Type:
application/json; charset=utf-8,就是说前端设置的不生效,到了此处很无解纳闷,不能重设请求头吗(此处一万个问号❓);再换一种思路,设置headers: { 'Content-Type': 'multipart/form-data',},然后后端报了另一种错误”不允许修改header头部”,再次崩溃!!!!,不清楚reqwest这里怎末就不识别上传的是个文件,此处是个大难题?未解
方案:
工作还是要做的,毕竟需求是老大嘛,于是请教了一位大神,用了另一种上传组件【WebUploader】引入WebUploader的js放到component下引入,(这里文件内容,稍后复制到最底下,不支持上传文件) 页面上:
---------------------------这个是点击选择文件的 ----------------------------- 这个是回填文件名称 --------------------------------这个是真正意义上的上传
js:
componentDidMount() {
this.webUuploader();// 加载绑定上传函数
}
webUuploader() {
let self = this;
setTimeout(() => {
self.uploader = WebUploader.create({
pick: '#upload',//这个要给绑定事件的对象,
accept: {
title: 'files',
extensions: 'xls,xlsx',//此处可以修改,要求上传文件什么类型
mimeTypes: 'xls,xlsx'//此处可以修改,要求上传文件什么类型
},
scenario: 'smartPolicy',
threads: 1,
formData: { 'column': 6 },//这里可以额外上送想上送的参数
multiple: false,
server: configs.host + UploadExcel,
// fileSizeLimit: 10 * 1024 * 1024,
auto: false,//设置成false是不自动上传后台,true的话就是选择文件即上传
uploaded: (res, file) => {//这里是上传给后台返回的成功与否信息
if (res.responseCode == '000000') {alert('客户名单新增成功')} else { alert('客户名单新增失败') }
}
});
self.uploader.on('filesQueued', (file) => {
self.setState({
fileName: file[0].name,//获取上传的文件名
});
});
self.uploader.on('uploadStart', (file, co) => {
self.setState({
fileName: file.name,
}, () => {
console.log('文件名1', self.state.fileName)
});
});
// 自定义上传参数
self.uploader.on('uploadBeforeSend', (object, data, header) => {
header.acceptLanguage = 'zh_CN';
});
}, 100);
};
以下是WebUploader的js内容:
// import './index.scss';
import WebUploader from 'webuploader';
import CFNetwork, {
uploadFileData
} from 'utils/network/CFNetwork.js';
import api from 'configs';
// 异常提示,可以使用 global.UtilsWebuploadorIndexErrorMsg 重新定义
global.UtilsWebuploadorIndexErrorMsg = {
// 默认报错
error: '上传出错,请检查后重新上传!',
// 上传格式错误
type: '上传文件格式错误!',
// 文件太大
big: '上传文件太大'
};
// webuploader 辅助类,使用 create 创建 webuploader
export default {
/**
* 创建 webuploader
* @param options 配置可以参照 webuploader,也可以参考注释的代码
* @param interfaces 接口
{
upload: 上传
}
*/
create: (options, interfaces, host) => {
host = host || api.host;
if (interfaces == null) {
if (!/\/$/.test(host)) {
host = host + '/';
}
interfaces = {
upload: host + 'file/upload'
};
}
options = Object.assign({
// 文件上传
server: interfaces.upload,
// 一旦有文件自动上传
auto: true,
// 在上传当前文件时,准备好下一个文件
prepareNextFile: true,
// 可以重复上传
duplicate: true,
// [function] 上传前判断是否可以上传
beforeFileQueued: null,
// [function] 上传后执行事件
uploaded: null,
// 多文件上传
multiple: true,
// 上传参数 key 值
uploadKeys: ['ext', 'name', 'fileMd5'],
// 应用场景
scenario: null,
// 0=增量 1=全量替换 目前只用于敏感词。
flagIncrement: 0,
// 敏感词时,未必填
robotId: null,
// 禁用拖拽功能
// dnd: '#dndVideo',
// 允许的格式
// accept: {
// title: 'video',
// extensions: 'mp4',
// mimeTypes: 'audio/mp4, video/mp4'
// },
// 单个文件最大字节 100MB
// fileSingleSizeLimit: 100 * 1024 * 1024,
// 文件最大字节
// fileSizeLimit: 1,
}, options);
options.pick = {
id: options.pick,
multiple: options.multiple
};
options.interfaces = interfaces;
let uploader = WebUploader.create(options);
bindWebuploadEvent(uploader, options);
return uploader;
}
};
// 创建一个 webuploader 用于自己操作事件
export function create(options) {
return WebUploader.create(options);
};
// 绑定处理事件
function bindWebuploadEvent(uploader, options) {
let uploadedTimer = null;
let {
scenario,
flagIncrement,
robotId
} = options;
uploader.on('uploadBeforeSend', (result, data) => {
let deferred = WebUploader.Deferred();
let name = result.file.name;
let ext = name.substring(name.lastIndexOf('.') + 1);
let uploadKeys = uploader.options.uploadKeys;
let params = {
scenario,
flagIncrement,
robotId
};
params[uploadKeys[0]] = ext;
params[uploadKeys[1]] = name;
params[uploadKeys[2]] = result.file.fileMd5;
Object.assign(data, uploadFileData(params));
return deferred.promise();
});
// 文件上传结束,通知合并分块
uploader.on('uploadSuccess', (file, response) => {
uploader.options.uploaded && uploader.options.uploaded(response, file);
});
// 错误的处理
uploader.on('error', (type, size, file) => {
let msg = global.UtilsWebuploadorIndexErrorMsg.error;
if (type == 'Q_TYPE_DENIED') {
msg = global.UtilsWebuploadorIndexErrorMsg.type;
} else if (type == 'Q_EXCEED_SIZE_LIMIT') {
msg = global.UtilsWebuploadorIndexErrorMsg.big;
} else if (type == 'F_EXCEED_SIZE') {
msg = global.UtilsWebuploadorIndexErrorMsg.big;
}
uploader.options.uploaded && uploader.options.uploaded({
code: -2,
msg
});
});
// 上传失败
uploader.on('uploadError', (file) => {
// console.log(file);
uploader.options.uploaded && uploader.options.uploaded({
code: -1,
msg: global.UtilsWebuploadorIndexErrorMsg.error
}, file);
});
// 全部文件执行完毕
uploader.on('uploadFinished', () => {
if (!uploadedTimer) {
uploadedTimer = setInterval(() => {
clearInterval(uploadedTimer);
uploadedTimer = null;
// uploader.reset();
}, 300);
}
});
};
WebUploader.Uploader.register({
'before-send-file': 'beforeSendFile'
}, {
beforeSendFile: function(file) {
let deferred = WebUploader.Deferred();
(new WebUploader.Uploader()).md5File(file).then(value => {
file.fileMd5 = value;
deferred.resolve();
});
return deferred.promise();
}
});