一.產品需求:
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]);
