react 拷贝上传文件

关键部分

     const haoroomsbox = document.getElementById('ant-upload-drag-area-id');
        haoroomsbox.addEventListener('paste', event => {
            const data = event.clipboardData || window.clipboardData;
            const items = data.items;
            let tempFile = null; // 存储文件数据
            if (items && items.length) {
                // 检索剪切板items
                for (let i = 0; i < items.length; i++) {
                    if (items[i].type.indexOf('image') !== -1) {
                        tempFile = items[i].getAsFile();
                        break;
                    }
                }
            }
            window.willUploadFileList = tempFile;
            event.preventDefault();
            submitUpload(tempFile, fileList);
        });
import React, { useEffect, useState, useRef } from 'react';
import { InboxOutlined } from '@ant-design/icons';
import { Modal, Upload } from 'antd';
import useToken from '@/hooks/useToken';
import { useMount, useUnmount } from 'ahooks';

const Dragger = Upload.Dragger;

const MAX_FILE_SIZE = 8;
const UNIT = 1024 * 1024;

const defaultBeforeUpload = file => {
    const fileType = ['jpg', 'jpeg', 'png', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf'];
    // 文件显示
    return new Promise((resolve, reject) => {
        const type = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
        if (fileType.indexOf(type) === -1) {
            Modal.warning({
                maskClosable: true,
                title: '文件须为word、excel、ppt、pdf、图片!',
            });
            reject(file);
        } else if (file.size > MAX_FILE_SIZE * UNIT) {
            Modal.warning({
                maskClosable: true,
                title: `单个文件大小不能超过${MAX_FILE_SIZE}M!`,
            });
            reject(file);
        } else {
            resolve(file);
        }
    });
};

const defaultOnDownload = file => {
    if (file?.url || file?.response?.XCmdrResult?.url) {
        window.open(file.url, '_blank');
    }
};

const createFileObject = file => {
    const fileObject = {
        lastModified: file.lastModified,
        lastModifiedDate: file.lastModifiedDate,
        name: file.name,
        size: file.size,
        type: file.type,
        uid: file.uid,
    };
    return fileObject;
};

const AttachmentsDragger = ({
    action,
    className,
    files,
    multiple = false,
    name,
    style,
    onBeforeUpload,
    onChange,
    onDownload,
    onRemove,
    isPaste = false,
    ...res
}) => {
    const [fileList, setFileList] = useState([]);
    const token = useToken();
    const fileListRef = useRef([]);
    useMount(() => {
        if (!isPaste) {
            return;
        }
        const haoroomsbox = document.getElementById('ant-upload-drag-area-id');
        haoroomsbox.addEventListener('paste', event => {
            const data = event.clipboardData || window.clipboardData;
            const items = data.items;
            let tempFile = null; // 存储文件数据
            if (items && items.length) {
                // 检索剪切板items
                for (let i = 0; i < items.length; i++) {
                    if (items[i].type.indexOf('image') !== -1) {
                        tempFile = items[i].getAsFile();
                        break;
                    }
                }
            }
            window.willUploadFileList = tempFile;
            event.preventDefault();
            submitUpload(tempFile);
        });
    });
    useEffect(() => {
        fileListRef.current = [...files];
        setFileList(files || []);
    }, [files]);
    const submitUpload = (file, temList) => {
        if (!file) {
            return;
        }
        const xhr = new XMLHttpRequest();
        const formdata = new FormData();
        formdata.append('upload_file', file);
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                const data = JSON.parse(xhr.response);
                if (data?.XCmdrCode === 0) {
                    file = {
                        ...file,
                        response: data,
                        originFileObj: createFileObject(file),
                        id: new Date().getTime(),
                        status: 'done',
                        name: data?.XCmdrResult?.path || file.name,
                    };
                    setFileList([...fileListRef.current, file]);
                    onChange(_, [...fileListRef.current, file]);
                }
            }
        };
        xhr.open('POST', `https://admin-api.zhgcloud.com/attachments?token=${token}`);
        xhr.send(formdata);
    };

    const draggerProps = {
        action,
        fileList,
        name,
        multiple,
        withCredentials: true,
        beforeUpload: onBeforeUpload || defaultBeforeUpload,
        ...res,
        onChange: info => {
            let newFiles = [...info.fileList];
            if (!multiple) {
                // 只保留最后一个文件
                newFiles = newFiles.slice(-1);
            }
            // 由于为组件传入了fileList属性,使之成为了受控组件,所以要在上传完成之前更新fileList,否则onChange只会执行一次。
            setFileList(newFiles);
            const { response, status } = info.file;
            const url = response?.XCmdrResult?.url;
            if (status === 'done' && url && typeof onChange === 'function') {
                onChange(info, newFiles);
            } else if (status === 'error') {
                message.error('上传文件失败');
            }
        },
        onDownload: onDownload || defaultOnDownload,
        onRemove: file => {
            const freshFiles = fileList.filter(ele => ele.uid !== file.uid);
            setFileList(freshFiles);
            if (typeof onRemove === 'function') {
                onRemove(file, freshFiles);
            }
        },
    };
    useUnmount(() => {
        const haoroomsbox = document.getElementById('ant-upload-drag-area-id');
        if (haoroomsbox) {
            haoroomsbox.removeEventListener('paste', () => {});
        }
    });
    return (
        <div className={className} style={style || { width: 340 }} id="ant-upload-drag-area-id">
            <Dragger {...draggerProps}>
                <p className="ant-upload-drag-icon">
                    <InboxOutlined />
                </p>
                <p className="ant-upload-text">点击或将文件拖拽到这里上传</p>
                <p className="ant-upload-hint">支持扩展名: .doc .docx .xls .ppt .pdf .jpg...</p>
            </Dragger>
        </div>
    );
};

export default AttachmentsDragger;

拷贝上传图片

import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle, onBeforeUpload } from 'react';
import { PlusOutlined } from '@ant-design/icons';
import { Upload, Modal } from 'antd';
import { saveAs } from 'file-saver';
import FileViewer from '@/components/FileViewer';
import useToken from '@/hooks/useToken';
import { useMount, useUnmount } from 'ahooks';

const MAX_FILE_SIZE = 8;
const UNIT = 1024 * 1024;
function getBase64(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
    });
}
const createFileObject = file => {
    const fileObject = {
        lastModified: file.lastModified,
        lastModifiedDate: file.lastModifiedDate,
        name: file.name,
        size: file.size,
        type: file.type,
        uid: file.uid,
    };
    return fileObject;
};
const defaultOnDownload = file => {
    // if (file?.url || file?.response?.XCmdrResult?.url) {
    //     window.open(file.url, '_blank');
    // }
    const url = file?.url || file?.response?.XCmdrResult?.url;
    saveAs(url, `${file?.name || file?.url || ''}`);
};
const defaultBeforeUpload = file => {
    const fileType = ['jpg', 'jpeg', 'png'];
    // 文件显示
    return new Promise((resolve, reject) => {
        const curType = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
        if (!fileType.includes(curType)) {
            Modal.warning({
                maskClosable: true,
                title: '图片格式须为jpg、jpeg、png!',
            });
            // reject(file);
            return Upload.LIST_IGNORE;
        } else if (file.size > MAX_FILE_SIZE * UNIT) {
            Modal.warning({
                maskClosable: true,
                title: `单个图片大小不能超过${MAX_FILE_SIZE}M!`,
            });
            return Upload.LIST_IGNORE;
        } else {
            resolve(file);
        }
    });
};
const UploadPicture = ({
    refChildPicture,
    limit = 3,
    action,
    onRemove,
    onChange,
    onDownload,
    pictures = [],
    isPaste = false,
    multiple = true,
    ...res
}) => {
    const [fileList, setFileList] = useState([]);
    const [url, setUrl] = useState('');
    const token = useToken();
    const fileListRef = useRef([]);
    useEffect(() => {
        fileListRef.current = [...pictures];
        setFileList([...pictures]);
    }, [pictures]);

    // 图片属性配置
    const pictureProps = {
        action: `https://admin-api.zhgcloud.com/attachments?token=${token}`,
        name: 'upload_file',
        listType: 'picture-card',
        fileList,
        multiple,
        ...res,
        beforeUpload: onBeforeUpload || defaultBeforeUpload,
        onChange: ({ file, fileList }) => {
            let newFiles = [...fileList];
            if (!multiple) {
                // 只保留最后一个文件
                newFiles = newFiles.slice(-1);
            }
            if (typeof onChange === 'function') {
                onChange(file, newFiles);
            }
        },
        onRemove: file => {
            const freshFiles = fileList?.filter(ele => ele.uid !== file.uid);
            if (typeof onRemove === 'function') {
                onRemove(file, freshFiles);
            }
        },
        onPreview: async file => {
            if (!file.url && !file.preview) {
                file.preview = await getBase64(file.originFileObj);
            }
            setUrl(file?.url || file?.response?.XCmdrResult?.url || file.previe);
        },
        onDownload: onDownload || defaultOnDownload,
    };
    useImperativeHandle(refChildPicture, () => {
        // return返回的值就可以被父组件获取到
        return {
            getFileData() {
                return {
                    fileList,
                };
            },
        };
    });
    useMount(() => {
        if (!isPaste) {
            return;
        }
        const haoroomsbox = document.getElementById('ant-upload-picture-area-id');
        haoroomsbox.addEventListener('paste', event => {
            // console.log('paste__');
            const data = event.clipboardData || window.clipboardData;
            const items = data.items;
            let tempFile = null; // 存储文件数据
            if (items && items.length) {
                // 检索剪切板items
                for (let i = 0; i < items.length; i++) {
                    if (items[i].type.indexOf('image') !== -1) {
                        tempFile = items[i].getAsFile();
                        break;
                    }
                }
            }
            window.willUploadPictureList = tempFile;
            event.preventDefault();
            submitUpload(tempFile);
        });
    });
    const submitUpload = file => {
        if (!file) {
            return;
        }
        if (fileList && fileList.length >= limit) {
            return;
        }
        // console.log('submitUpload', this, fileListRef.current);
        const xhr = new XMLHttpRequest();
        const formdata = new FormData();
        formdata.append('upload_file', file);
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                const data = JSON.parse(xhr.response);
                if (data?.XCmdrCode === 0) {
                    // 图片转换成base64编码作为缩略图
                    const reader = new FileReader();
                    // 监听图片转换完成
                    reader.addEventListener(
                        'load',
                        () => {
                            // console.log('reader', reader.result);
                            // ...接入antd upload 的 filelist 中
                            const temFile = {
                                ...file,
                                response: data,
                                originFileObj: createFileObject(file),
                                id: new Date().getTime(),
                                status: 'done',
                                name: data?.XCmdrResult?.path || file.name,
                                url: data?.XCmdrResult?.url,
                                thumbUrl: reader.result,
                            };
                            // console.log('上传完成', file, fileListRef.current);
                            if (typeof onChange === 'function') {
                                onChange(_, [...fileListRef.current, temFile]);
                            }
                        },
                        false,
                    );
                    reader.readAsDataURL(file);
                }
            }
        };
        xhr.open('POST', `https://admin-api.zhgcloud.com/attachments?token=${token}`);
        xhr.send(formdata);
    };
    useUnmount(() => {
        const haoroomsbox = document.getElementById('ant-upload-picture-area-id');
        haoroomsbox.removeEventListener('paste', () => {});
    });
    return (
        <div ref={refChildPicture} id="ant-upload-picture-area-id">
            <Upload {...pictureProps}>
                {fileList && fileList.length >= limit ? null : (
                    <div>
                        <PlusOutlined />
                        <div>上传图片</div>
                    </div>
                )}
            </Upload>
            <FileViewer url={url} onCancel={() => setUrl('')} />
        </div>
    );
};

export default forwardRef(UploadPicture);

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值