服务器之家

服务器之家 > 正文

Python基于React-Dropzone实现上传组件的示例代码

时间:2021-12-20 00:31     来源/作者:DisonTangor

这次我要讲述的是在React-Flask框架上开发上传组件的技巧。我目前主要以React开发前端,在这个过程中认识到了许多有趣的前端UI框架——React-BootstrapAnt DesignMaterial UIBulma等。而比较流行的上传组件也不少,而目前用户比较多的是jQuery-File-UploadDropzone,而成长速度快的新晋有Uppyfilepond。比较惋惜的是Fine-Uploader的作者自2018年后就决定不再维护了,原因作为后来者的我就不多过问了,但请各位尊重每一位开源作者的劳动成果。

这里我选择React-Dropzone,原因如下:

  • 基于React开发,契合度高
  • 网上推荐度高,连Material UI都用他开发上传组件
  • 主要以 Drag 和 Drop 为主,但是对于传输逻辑可以由开发者自行设计。例如尝试用socket-io来传输file chunks。对于node全栈估计可行,但是我这里使用的是Flask,需要将Blob转ArrayBuffer。但是如何将其在Python中读写,我就没进行下去了。

实例演示

1. axios上传普通文件:

通过yarn将react-dropzone和引入:

?
1
yarn add react-dropzone axios

前端js如下(如有缺失,请自行修改):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import React, {
    useState,
    useCallback,
    useEffect,
} from 'react';
import {useDropzone} from 'react-dropzone';
import "./dropzone.styles.css"
import InfiniteScroll from 'react-infinite-scroller';
import {
    List,
    message,
    // Avatar,
    Spin,
} from 'antd';
import axios from 'axios';
 
/**
* 计算文件大小
* @param {*} bytes
* @param {*} decimals
* @returns
*/
function formatBytes(bytes, decimals = 2) {
    if (bytes === 0) return '0 Bytes';
 
    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
 
    const i = Math.floor(Math.log(bytes) / Math.log(k));
 
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
 
/**
* Dropzone 上传文件
* @param {*} props
* @returns
*/
function DropzoneUpload(props) {
    const [files, setFiles] = useState([])
    const [loading, setLoading] = useState(false);
    const [hasMore, setHasMore] = useState(true);
 
    const onDrop = useCallback(acceptedFiles => {
        setLoading(true);
        const formData = new FormData();
        smallFiles.forEach(file => {
            formData.append("files", file);
        });
        axios({
            method: 'POST',
            url: '/api/files/multiplefiles',
            data: formData,
            headers: {
                "Content-Type": "multipart/form-data",
            }
        })
        then(resp => {
            addFiles(acceptedFiles);
            setLoading(false);
        });
    }, [files]);
 
    // Dropzone setting
    const { getRootProps, getInputProps } = useDropzone({
        multiple:true,
        onDrop,
    });
 
    // 删除附件
    const removeFile = file => {
        const newFiles = [...files]
        newFiles.splice(newFiles.indexOf(file), 1)
        setFiles(newFiles)
    }
 
    useEffect(() => {
        // init uploader files
        setFiles([])
    },[])
 
    return (
        <section className="container">
        <div {...getRootProps({className: 'dropzone'})}>
            <input {...getInputProps()} />
            <p>拖动文件或点击选择文件

相关文章

热门资讯

返回顶部