亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python基于React-Dropzone實(shí)現(xiàn)上傳組件的示例代碼

瀏覽:75日期:2022-07-29 08:14:40
目錄實(shí)例演示1. axios上傳普通文件:2. 大文件導(dǎo)入:結(jié)語(yǔ)

這次我要講述的是在React-Flask框架上開(kāi)發(fā)上傳組件的技巧。我目前主要以React開(kāi)發(fā)前端,在這個(gè)過(guò)程中認(rèn)識(shí)到了許多有趣的前端UI框架——React-Bootstrap、Ant Design、Material UI、Bulma等。而比較流行的上傳組件也不少,而目前用戶(hù)比較多的是jQuery-File-Upload和Dropzone,而成長(zhǎng)速度快的新晉有Uppy和filepond。比較惋惜的是Fine-Uploader的作者自2018年后就決定不再維護(hù)了,原因作為后來(lái)者的我就不多過(guò)問(wèn)了,但請(qǐng)各位尊重每一位開(kāi)源作者的勞動(dòng)成果。

這里我選擇React-Dropzone,原因如下:

基于React開(kāi)發(fā),契合度高 網(wǎng)上推薦度高,連Material UI都用他開(kāi)發(fā)上傳組件 主要以 Drag 和 Drop 為主,但是對(duì)于傳輸邏輯可以由開(kāi)發(fā)者自行設(shè)計(jì)。例如嘗試用socket-io來(lái)傳輸file chunks。對(duì)于node全棧估計(jì)可行,但是我這里使用的是Flask,需要將Blob轉(zhuǎn)ArrayBuffer。但是如何將其在Python中讀寫(xiě),我就沒(méi)進(jìn)行下去了。 實(shí)例演示1. axios上傳普通文件:

通過(guò)yarn將react-dropzone和引入:

yarn add react-dropzone axios

前端js如下(如有缺失,請(qǐng)自行修改):

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’;/*** 計(jì)算文件大小* @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 filessetFiles([]) },[]) return (<section className='container'><div {...getRootProps({className: ’dropzone’})}> <input {...getInputProps()} /> <p>拖動(dòng)文件或點(diǎn)擊選擇文件😊</p></div><div className='demo-infinite-container'> <InfiniteScrollinitialLoad={false}pageStart={0}loadMore={handleInfiniteOnLoad}hasMore={!loading && hasMore}useWindow= {false} ><List dataSource={files} renderItem={item=> (<List.Item actions={[// <a key='list-loadmore-edit'>編輯</a>, <a key='list-loadmore-delete' onClick={removeFile}>刪除</a> ]} // extra={// } key={item.path}> <List.Item.Meta avatar={ <> {!!item.type && [’image/gif’, ’image/jpeg’, ’image/png’].includes(item.type) &&<img width={100} alt=’logo’ src={item.preview}/> } </>}title={item.path}description={formatBytes(item.size)} /></List.Item> )}> {loading && hasMore && (<div className='demo-loading-container'> <Spin /></div> )}</List> </InfiniteScroll></div></section> );}

flask代碼:

def multiplefiles():if ’files’ not in request.files: return jsonify({’message’: ’沒(méi)有文件!’}), 200files = request.files.getlist(’files’)for file in files: if file:# 通過(guò)拼音解決secure_filename中文問(wèn)題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. 大文件導(dǎo)入:

通過(guò)file.slice()方法生成文件的chunks。不要用Promise.all容易產(chǎn)生非順序型的請(qǐng)求,導(dǎo)致文件損壞。

js代碼:

const promiseArray = largeFiles.map(file => new Promise((resolve, reject) => { const chunkSize = CHUNK_SIZE; const chunks = Math.ceil(file.size / chunkSize); let chunk = 0; let chunkArray = new Array(); while (chunk <= chunks) {let offset = chunk * chunkSize;let slice = file.slice(offset, offset+chunkSize)chunkArray.push([slice, offset])++chunk; } const chunkUploadPromises = (slice, offset) => {const largeFileData = new FormData();largeFileData.append(’largeFileData’, slice)return new Promise((resolve, reject) => { axios({method: ’POST’,url: ’/api/files/largefile’,data: largeFileData,headers: { 'Content-Type': 'multipart/form-data'} }) .then(resp => {console.log(resp);resolve(resp); }) .catch(err => {reject(err); })}) }; chunkArray.reduce( (previousPromise, [nextChunk, nextOffset]) => {return previousPromise.then(() => { return chunkUploadPromises(nextChunk, nextOffset);}); }, Promise.resolve()); resolve();}))

flask代碼:

filename = secure_filename(’’.join(lazy_pinyin(filename)))Path(UPLOAD_FOLDER + ’/’ + file_info[’dir_path’]).mkdir(parents=True, exist_ok=True)save_path = os.path.join(UPLOAD_FOLDER + ’/’ + file_info[’dir_path’], filename)# rm file if existsif offset == 0 and save_path.exists(filename): os.remove(filename)try: with open(save_path, ’ab’) as f:f.seek(offset)f.write(file.stream.read())print('time: '+ str(datetime.now())+' offset: ' + str(offset))except OSError: return jsonify({’Could not write to file’}), 500結(jié)語(yǔ)

文件傳輸一直都是HTTP的痛點(diǎn),尤其是大文件傳輸。最好的方式是自己做個(gè)Client,通過(guò)FTP和FTPS的協(xié)議進(jìn)行傳輸。第二種來(lái)自于大廠很中心化的方法,通過(guò)文件的checksum來(lái)確定文件是否已經(jīng)上傳了,來(lái)營(yíng)造秒傳的效果。第三種來(lái)自去中心化的Bittorrent的方法每一個(gè)用戶(hù)做文件種子,提供文件傳輸?shù)妮o助,目前國(guó)內(nèi)并沒(méi)有普及使用。

到此這篇關(guān)于Python基于React-Dropzone實(shí)現(xiàn)上傳組件的示例代碼的文章就介紹到這了,更多相關(guān)Python React-Dropzone上傳組件內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 久久永久免费中文字幕 | 青木玲中文字幕一区二区 | 欧美成人h版整片合集 | 国产精品久久久久久福利漫画 | 1024cc香蕉在线观看免费 | 国产原创中文字幕 | 欧美专区一区二区三区 | 国产成人亚洲毛片 | 久免费视频| 国产成人影院在线观看 | 国内精品自产拍在线观看91 | 国产成人一区二区三区视频免费 | 欧美一级视频在线高清观看 | 亚洲欧美国产毛片在线 | 午夜寻花高颜值极品女神 | 国产亚洲精品久久久久久 | 国产精品无码永久免费888 | 九色在线免费观看 | 永久免费毛片在线播放 | 欧美啪啪网站 | 香港aa三级久久三级不卡 | 久久精品图片 | 亚洲香蕉久久综合网 | 久久久久久久国产视频 | 国产1024在线永久免费观看 | 国产一区二区免费福利片 | 久久视频免费在线观看 | 亚洲国内精品 | 又黄又爽视频 | 天天色综| 亚洲区视频 | 国产精品1024在线观看免费看 | 国产麻豆精品一区二区 | 女性一级全黄生活片在线播放 | 免费看片黄色 | 国产高清看片日韩欧美久久 | 黄色影片一级 | 国产精品三级国语在线看 | 亚洲在线一区二区三区 | 国产精品极品 | 亚洲色图国产精品 |