简单实现文件上传、下载、预览、拖曳

import { useMemo, useState } from "react";
import classes from "./Upload.module.css";
import { dateFormat } from "../../helpers/helper"
import ButtonMenu from "../button-menu/ButtonMenu";
import Enumerable from "linq";
import { toast } from "react-toastify";
import { PhotoProvider, PhotoConsumer } from 'react-photo-view';

export default function Upload({ }) {
    const [files, setFiles] = useState([]);
    const [sort, setSort] = useState('default');

    const preventDefault = function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
    }

    const calcFiles = useMemo(() => {
        switch (sort) {
            case 'size':
                return Enumerable.from(files).orderByDescending(u => u.size).toArray();
            case 'date':
                return Enumerable.from(files).orderByDescending(u => u.lastModifiedDate).toArray();
            case 'name':
                return Enumerable.from(files).orderByDescending(u => u.name).toArray();
            default: return files;
        }
    }, [sort, files.length]);

    const dropHandler = function (ev) {
        preventDefault(ev);
        var items = ev.target.files || ev.dataTransfer.items;
        if (items && items.length == 0) return;

        const file = ev.dataTransfer ? items[0].getAsFile() : items[0];
        if (!file) return;
        // limit size 10M
        var size = parseFloat(file.size / 1024).toFixed(2);
        if (size > 10 * 1024) toast.warn("over 10M sizes.");

        setFiles(files => {
            return files.concat({
                id: Date.now().toString(36),
                name: file.name,
                type: file.type,
                size: size,
                path: window.URL.createObjectURL(file),
                isImage: file.type.indexOf("image") > -1,
                date: dateFormat("mm/dd/YYYY", file.lastModifiedDate),
                lastModifiedDate: file.lastModifiedDate
            })
        });

        console.log(file);
    }

    return <>
        <ButtonMenu
            className={classes.sort}
            direction="right"
            type="button"
            text="More"
            options={[
                {
                    text: "Sort By Name",
                    onClick: (ev) => {
                        setSort('name');
                    }
                },
                {
                    text: "Sort by Date",
                    onClick: (ev) => {
                        setSort('date');
                    }
                },
                {
                    text: "Sort By Size",
                    onClick: (ev) => {
                        setSort('size');
                    }
                },
                {
                    text: "List",
                },
            ]}
        />
        <div className={classes.container}
            onDrop={dropHandler}
            onDragEnter={preventDefault}
            onDragOver={preventDefault}
            onDragLeave={preventDefault}>
            <div className={classes.tip}>Drop files to attach, or <div className={classes.browse}>browse<input type="file" className={classes.file} onChange={dropHandler} /></div>.</div>
            <div className={classes.preview}>
                {calcFiles && calcFiles.map(item => <div className={classes.item} key={item.id}>
                    <div className={classes.itemMain}>
                        {item.isImage ? <PhotoProvider className={classes.viewImage}>
                            <PhotoConsumer src={item.path} intro={item.path}>
                                <img src={item.path} height="100%" style={{ display: 'block', maxWidth: '100%', margin: '0 auto',cursor:'pointer' }} />
                            </PhotoConsumer>
                        </PhotoProvider> : <div className={classes.fileIcon}>File</div>}
                    </div>
                    <div className={classes.fileName}>{item.name}</div>
                    <div className={classes.description}>
                        <span>{item.date}</span>
                        <span>{item.size} KB</span>
                        <a href={item.path} download={item.name} style={{ color: '#8cb5f3' }}>download</a>
                    </div>
                </div>)}
            </div>
        </div></>
}

  

如果您觉得本文对你有用,不妨帮忙点个赞,或者在评论里给我一句赞美,小小成就都是今后继续为大家编写优质文章的动力,百小僧拜谢! 欢迎您持续关注我的博客:)
原文地址:https://www.cnblogs.com/baiqian/p/15195024.html