一.产品需求:
1. 在表格中上传图片,图片上传需要加上服务器需要的请求头(参数签名) 把图片上传到指定的服务器 服务器返回一个id
2. 拿到id调用获取图片的接口 获取后端返回一个图片文件 进行base64转化 放入img图片中 进行图片展示
二.实现步骤
1.使用Upload的customRequest属性 实现自定义的请求方式
封装文件上传方法 http.js
import axios from 'axios'; const http = axios.create({ headers: { appId: '8a8a8', 'TM-Header-AppId': 'xixi', 'Content-Type': 'multipart/form-data', }, timeout: TIME_OUT, baseURL: '/', }); http.interceptors.request.use( config => { if (config.method === 'get') { // get方式为图片展示 post方式为图片上传 // 给data赋值以绕过if判断 config.data = true; config.headers['Content-Type'] = 'application/json'; config.responseType = 'arraybuffer'; } return config; }, err => Promise.reject(err), ); .....
2.FormData 实现异步上传文件
// 自定义upload默认请求方式 const customRequest = (config: any) => { // 通过FormData构造函数创建一个空对象 const formData = new FormData(); // 通过append方法来追加数据 formData.append('file', config.file); // http({ url: `/api/fs-service/file/upload`, method: 'POST', data: formData, }) .then(res => {
// 后端返回一个id const { id } = res.data.data;
// 通过id去调用get方式 返回一个二进制流 getThumbUrl(id) .then((response: any) => {
// 通过二进制流转化为base64图片 const base64Url = getBase64Img(response); res.data.base64Url = base64Url; config.onSuccess(res.data); }) .catch((e: any) => { console.log(e); }); }) .catch(error => { config.onError(new Error('文件上传失败')); }); };
// 图片展示 必须传递头信息 const getThumbUrl = (id: any) => { let ret = ''; if (id) { try { const res = http({ url: `${baseUrl.getFileUrl}api/fs-service/file/getFile`, method: 'GET', params: { fileId: id, }, }); ret = res; } catch (e) { console.error(e); } } return ret; };
后端返回一个带有id的结构
4.请求头中添加responseType = 'arraybuffer'; 才会返回二进制流图片
转化为base64位图片:
// 二进制流图片转化为base64位图片展示 const getBase64Img = (res: any) => { const bufferUrl = btoa( new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ''), ); const base64Url = `data:image/png;base64,${bufferUrl}`; return base64Url; };
渲染图片
// 渲染文件的列表内容 const buildUploadList = (fileList: any) => { return fileList.map((file: any, index?: any) => { const {response = {}, uid } = file; const { base64Url } = isDone ? response : {}; return ( <div key={uid}> <span className="ant-upload-span"> {<img src={base64Url} alt="" />} </span> </div> ); }); };
三.初始化图片异步回显
const getFile = (reValue: string[]) => { if (reValue && reValue.length > 0) { const allReq = reValue.map((v: any) => { const { response } = v; if (response.id) { try { return getThumbUrl(response.id).then((item: any) => { const base64Url = getBase64Img(item); return { status: 'done', uid: response.id, response: { id: response.id, base64Url, }, }; }); } catch (e) { console.error(e); } } }); return Promise.all(allReq).then((urlList: any) => { const newUrlList = urlList.filter((val: any) => { return val; }); setFileList(newUrlList); }); } return []; }; useEffect(() => { if (!value) { return; } //。。。。。相同导致的重新渲染 这里可以做一些优化处理操作 if ( value.length !== fileList.length || JSON.stringify(value) !== JSON.stringify(fileList) ) { getFile(value); } }, [value]);