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