Python基于React?Dropzone实现上传组件的示例代码
Python基于React?Dropzone实现上传组件的示例代码,博智网带你了解详细信息 。
目录
- 实例演示
- 1. axios上传普通文件:
- 2. 大文件导入:
- 结语
这次我要讲述的是在React-Flask框架上开发上传组件的技巧 。我目前主要以React开发前端 , 在这个过程中认识到了许多有趣的前端UI框架——React-Bootstrap、Ant Design、Material UI、Bulma等 。而比较流行的上传组件也不少 , 而目前用户比较多的是jQuery-File-Upload和Dropzone , 而成长速度快的新晋有Uppy和filepond 。比较惋惜的是Fine-Uploader的作者自2018年后就决定不再维护了 , 原因作为后来者的我就不多过问了 , 但请各位尊重每一位开源作者的劳动成果 。
这里我选择React-Dropzone,原因如下:
- 基于React开发 , 契合度高
- 网上推荐度高 , 连Material UI都用他开发上传组件
- 主要以 Drag 和 Drop 为主 , 但是对于传输逻辑可以由开发者自行设计 。例如尝试用socket-io来传输file chunks 。对于node全栈估计可行 , 但是我这里使用的是Flask , 需要将Blob转ArrayBuffer 。但是如何将其在Python中读写 , 我就没进行下去了 。
实例演示
1. axios上传普通文件:
通过yarn将react-dropzone和引入:
yarn add react-dropzone axios
前端js如下(如有缺失 , 请自行修改):
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 = https://www.yf-zs.com/redian/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 settingconst { getRootProps, getInputProps } = useDropzone({multiple:true,onDrop,});// 删除附件const removeFile = file => {const newFiles = [...files]newFiles.splice(newFiles.indexOf(file), 1)setFiles(newFiles)}useEffect(() => {// init uploader filessetFiles([])},[])return (<section className="container"><p {...getRootProps({className: 'dropzone'})}><input {...getInputProps()} /><p>拖动文件或点击选择文件😊</p></p><p className="demo-infinite-container"><InfiniteScrollinitialLoad={false}pageStart={0}loadMore={handleInfiniteOnLoad}hasMore={!loading && hasMore}useWindow= {false}><ListdataSource={files}renderItem={item=> (<List.Itemactions={[// <a key="list-loadmore-edit">编辑</a>,<a key="list-loadmore-delete" onClick={removeFile}>删除</a>]}// extra={// }key={item.path}><List.Item.Metaavatar={<>{!!item.type && ['image/gif', 'image/jpeg', 'image/png'].includes(item.type) &&<imgwidth={100}alt='logo'src=https://www.yf-zs.com/redian/{item.preview}/>}>}title={item.path}description={formatBytes(item.size)}/>)}>{loading && hasMore && (
flask代码:
def multiplefiles():if 'files' not in request.files:return jsonify({'message': '没有文件!'}), 200files = request.files.getlist('files')for file in files:if file:# 通过拼音解决secure_filename中文问题filename = secure_filename(''.join(lazy_pinyin(file.filename))Path(UPLOAD_FOLDER + '/' + file_info['dir_path']).mkdir(parents=True, exist_ok=True)file.save(os.path.join(UPLOAD_FOLDER + '/' + file_info['dir_path'], filename))return jsonify({'message': '保存成功!!'})
2. 大文件导入:
通过file.slice()方法生成文件的chunks 。不要用Promise.all容易产生非顺序型的请求 , 导致文件损坏 。
js代码:
推荐阅读
- 基佬用的小蓝是什么吗
- 确立大战略的首要原则是
- python怎么让程序重复运行
- 营销战略是基于业务层的战略吗
- 融资类型包括哪些
- 为什么摩托车还要用化油器
- 如何将python生成exe
- BTD是什么模式
- 卡罗拉是tnga架构吗
- 如何用Python编写应用程序
