React結合Antd的Upload實現自定義圖片上傳和后端二進制流異步圖片回顯


一.產品需求:

  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]);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM