浏览器文件分段断点上传简单示例(python 篇)

简介: 后端使用 Python Flask前端原理实现:1.获取文件特征码2.截取文件信息和对文件分段3.校验服务器是否存在同样特征码的没上传完的文件4.

后端使用 Python Flask

前端原理实现:

1.获取文件特征码
2.截取文件信息和对文件分段
3.校验服务器是否存在同样特征码的没上传完的文件
4.如过有同样特征码文件获取上传进度
5.否则进度从0开始
6.循环异步按顺序上传分段文件
7.如果上传完成提示成功

后端原理实现:

1.接收request(文件hash)参数
2.判断文件是否是中断上传的
3.如果存在hash文件夹获取文件夹下文件段数量返回给前端
4.不存在返回0或空字符串

5.如果前端返回上传的文件段,则保存文件段并给文件段标识索引
6.如果上传完成合并文件,删除文件段

html代码

代码以单个文件上传为例,使用hashMe.js获取特征码

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
    <script type="text/javascript" src="md5.js"></script>
    <script src="hashme.js"></script>
</head>

<body>
    <input type="file" onchange="hhh(this.files[0])" />
    <button onclick="uploadCk()">测试</button>
    <script>
        var up_f;//需要上传的信息
        var fileSplitSize = 1024 * 1024 * 2; //以2MB为一个分片
        function hhh(f) { 
            if (true) { //假设这是判断文件大小
                var hash = new hashMe(f, function(msg) {
                    up_f = new Object();
                    up_f.hash = msg;
                    up_f.name = f.name;
                    up_f.size = f.size;
                    up_f.shardCount = Math.ceil(f.size / fileSplitSize); //总片数
                    up_f.shard = [];//文件段
                    for (var i = 0; i < up_f.shardCount; i++) {
                        var start = i * fileSplitSize;
                        var end = Math.min(f.size, start + fileSplitSize);
                        up_f.shard[up_f.shard.length] = f.slice(start, end);//保存分段
                    }
                });
            }
        }

        function uploadCk() { //上传前检查 
            $.ajax({
                url: "/upload_ck",
                type: "get",
                data: {
                    hash: up_f.hash
                },
                success: function(data) {
                    if (data != "") {
                        upload(Number(data));//调用上传(索引为服务器存在的文件段索引)
                    } else { 
                        upload(0);//调用上传
                    }
                }
            });
        }

        function upload(loadIndex) { //上传
            var form = new FormData();
            form.append("hash", up_f.hash);
            form.append("name", up_f.name);
            form.append("size", up_f.size);
            form.append("shardCount", up_f.shardCount);
            form.append("blob", up_f.shard[loadIndex]);
            form.append("sdIndex", loadIndex);
            console.log("sdIndex:" + loadIndex + ",shardCount:" + up_f.shardCount)
            $.ajax({
                url: "/upload",
                type: "POST",
                data: form,
                async: true, 
                processData: false, //很重要,告诉jquery不要对form进行处理
                contentType: false, //很重要,指定为false才能形成正确的Content-Type
                success: function(data) {
                    data = Number(data) + 1;
                    if (data <= up_f.shardCount) {
                        console.log("data:" + data);
                        upload(data);
                    } else {
                        console.log("上传完毕");
                    }
                }
            });
        }
    </script>
</body>
</html>

Python代码

为示例写的Python代码有些不规范大家尽量不要模仿我这种写法(mime下载)

from flask import Flask, url_for,request 
import codecs,re,os
import urllib.parse,mime
import shutil
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter):
    def __init__(self, map, *args):
        self.map = map
        self.regex = args[0]
        
app = Flask(__name__)
mim=mime.types
app.config['UPLOAD_FOLDER'] = 'uploads/'#保存文件位置

app.url_map.converters['regex'] = RegexConverter
@app.route('/<regex(".*"):url>')
def index(url):
    ps=urllib.parse.unquote(url)   
    if ps=="upload":
        return upload()
    elif ps.split('?')[0]=="upload_ck":
        if os.path.exists("./"+app.config['UPLOAD_FOLDER']+str(request.args.get('hash') ) ):
            return str(len( os.listdir("./"+app.config['UPLOAD_FOLDER']+str(request.args.get('hash') )) )-1 )#返回文件段索引
        else:
            return ""
    bt=codecs.open(ps,'rb',"utf-8").read() 
    return  bt, 200, {'Content-Type': mim[url.split(".")[-1]]}

@app.route('/upload', methods=['POST'])
def upload():
    hashtxt=request.form['hash']
    sPs="./"+app.config['UPLOAD_FOLDER']+hashtxt+"/"
    if not os.path.exists(sPs):#文件夹不存在
        os.makedirs(sPs)#创建hash文件夹
    uploaded_files = request.files.getlist("blob")#获取文件流集
    filePs=hashtxt+"/"+request.form['name']+".part"+request.form['sdIndex'] #文件段保存路径
    for file in uploaded_files:  
        file.save(os.path.join(app.config['UPLOAD_FOLDER'],filePs ))#保存文件
    if (int(request.form['shardCount']))==(int(request.form['sdIndex'])):#判断上传完最后一个文件
        mergeFile(app.config['UPLOAD_FOLDER'],request.form['name'],hashtxt);#合并文件
        shutil.rmtree("./"+app.config['UPLOAD_FOLDER']+hashtxt)#删除
    return request.form['sdIndex']#返回段索引
 
        
def mergeFile(ps,nm,hs):#合并文件
    temp = open(ps+"/"+nm,'wb')#创建新文件
    count=len(os.listdir(ps+"/"+hs))
    for i in range(0,count):  
        fp = open(ps+"/"+hs+"/"+nm+".part"+str(i), 'rb')#以二进制读取分割文件
        temp.write(fp.read())#写入读取数据
        fp.close()  
    temp.close()

with app.test_request_context():    #输出url
    pass
if __name__ == '__main__': 
    app.debug = True
    app.run() 
示例就这么多,但实际问题上没那么简单,比如上传校验前可以先获取服务器中已经存在的同一特征码和大小的文件,然后直接复制文件到上传的目录或提示是否覆盖等等。当然你还可以优化比如上传分段后再上传时在进行分片然后对片执行同时上传之类的。
相关文章
|
16天前
|
Python
【python】python跨文件使用全局变量
【python】python跨文件使用全局变量
|
22天前
|
Web App开发 Python
在ModelScope中,你可以使用Python的浏览器自动化库
在ModelScope中,你可以使用Python的浏览器自动化库
15 2
|
24天前
|
监控 数据处理 索引
使用Python批量实现文件夹下所有Excel文件的第二张表合并
使用Python和pandas批量合并文件夹中所有Excel文件的第二张表,通过os库遍历文件,pandas的read_excel读取表,concat函数合并数据。主要步骤包括:1) 遍历获取Excel文件,2) 读取第二张表,3) 合并所有表格,最后将结果保存为新的Excel文件。注意文件路径、表格结构一致性及异常处理。可扩展为动态指定合并表、优化性能、日志记录等功能。适合数据处理初学者提升自动化处理技能。
21 1
|
29天前
|
存储 并行计算 Java
Python读取.nc文件的方法与技术详解
本文介绍了Python中读取.nc(NetCDF)文件的两种方法:使用netCDF4和xarray库。netCDF4库通过`Dataset`函数打开文件,`variables`属性获取变量,再通过字典键读取数据。xarray库利用`open_dataset`打开文件,直接通过变量名访问数据。文中还涉及性能优化,如分块读取、使用Dask进行并行计算以及仅加载所需变量。注意文件路径、变量命名和数据类型,读取后记得关闭文件(netCDF4需显式关闭)。随着科学数据的增长,掌握高效处理.nc文件的技能至关重要。
102 0
|
1月前
|
Python
python中文件和异常处理方法(三)
python中文件和异常处理方法(三)
19 0
|
16天前
|
C++ Python
【C++/Python】C++调用python文件
【C++/Python】C++调用python文件
|
16天前
|
JSON 数据处理 数据格式
Python中的文件读写操作详解
【4月更文挑战第2天】在Python中,文件读写操作是数据处理和程序开发的重要部分。通过文件,我们可以将信息持久化地保存在磁盘上,并在需要时读取和使用这些数据。Python提供了丰富的内置函数和模块,使得文件读写变得简单而高效。本文将详细介绍Python中文件读写的基本操作和常用方法。
|
28天前
|
开发者 Python
Python语言的文件及目录访问
Python语言的文件及目录访问
|
1月前
|
存储 数据管理 Serverless
Python实现:教你轻松统计文件夹下文件个数
Python实现:教你轻松统计文件夹下文件个数
23 0
|
1月前
|
Python
如何使用Python去除文件后缀名?
如何使用Python去除文件后缀名?
19 0

热门文章

最新文章