文件分片上传 python

服务端功能

上传分片保存

@app.route('/upload_filesliceprocess', methods=['POST'])
def upload_filesliceprocess():
    file = request.files['file']
    name_index = request.form['name_index']
    complete = request.form['complete']
    process = request.form['process']
    clienthash = request.form['clienthash']

    source_name = request.form['filename']
    filename = ''.join(source_name.split('.')[0:-1])
    file_path = fr'{SLICE_DATA}/{filename}'
    p_file_path = pd.Path(file_path)
    if not pd.Path.exists(p_file_path):
        os.makedirs(p_file_path)
    fileindex=fr'{file_path}/{name_index}'
    filename=fr'{file_path}/{name_index}'
    if(os.path.exists(fileindex)==False):
       
        file.save(filename)
    import utils
    
    hashserver=utils.calculate_md5(filename)
    if(clienthash==hashserver):
        return 'ok'
    else:
       return 'error'

    print(f'process:{round(float(process)*100, 2)}%')

合并分片功能

@app.route('/merge_file', methods=['POST'])
def merge_file():
    print('-------------------------------')
     
    filename = request.form['filename']
    print(filename)
    #splitfile=os.path.splitext(filename)
   
    #filename=splitfile[0]
   
    #ext=splitfile[1]
    filename, ext = os.path.splitext(filename)
    ext=ext.replace('.','')
    
    file_path= fr'{SLICE_DATA}/{filename}'
    combination_fun(file_path,filename,ext)
    return 'ok'

合并文件函数

def combination_fun(folder_path, source_name,ext):

    com_path = pd.Path(COMBINATION_DATA)
    if not pd.Path.exists(com_path):
        os.makedirs(com_path)

    ready_folder = os.listdir(folder_path)
    ready_sort_folder = sorted(ready_folder, key=lambda x: int(x.split('_')[-1]))
    with open(f'{COMBINATION_DATA}/{source_name}.{ext}', 'wb') as write_f:
        for item in ready_sort_folder:
            slice_item = os.path.join(folder_path, item)
            print(slice_item)
            with open(slice_item, "rb") as read_f:
                content = read_f.read()
                write_f.write(content)
    #删除缓存文件
    for item in ready_sort_folder:
            slice_item = os.path.join(folder_path, item)
            os.remove(slice_item)

前端

引用库   jquery Md5

  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

上传简单界面

   <input type="file" name="file" id="file">
    <button id="upload" onClick="uploadfile()">upload</button>
    <button id="mergedata" onClick="uploadcomplete()">mergedata</button>    
   <div class="rate_div" >
       上传进度:<span id="rate_nums">0</span>
            <progress id="downloadProgress" value="0"  max="100"></progress>
   </div>

上传脚本

<script type="text/javascript">
       
        var totalPieces=0;
    var nowUploadNums = 0;
    const MAX_RETRIES = 5; // 最大重试次数
    const CHUNK_SIZE = 100*1024 * 1024; // 1MB 分片大小
        
    let arr = [];
    let retries=[];
        //发送请求
    function displayProgress(percent) {
           
            
                document.getElementById('downloadProgress').value = percent;
               
         }

    function mergedata()
    {
        var blob = document.getElementById("file").files[0];
          
            var filesize = blob.size;
            var filename = blob.name;

    }
    function setRate(num) {
          var rateNums = document.getElementById('rate_nums');
          rateNums.innerHTML = num;
    }
    function uploadcomplete()
    {
        nowUploadNums ++;
        if(nowUploadNums >=totalPieces)
        {
        console.log('true')
        
                 var blob = document.getElementById("file").files[0];
           
                var filename = blob.name;
         var formData = new FormData();
                
                   formData.append("filename", filename);
                
          $.ajax({
                    url: '/merge_file',
                    type: 'POST',
                    cache: false,
                    data: formData,
        
                    processData: false,
                    contentType: false,
             
                }).done(function(res){
                   alert('合并成功');

                }).fail(function(res) {
            alert('合并失败');
            

                });
                                            
          }
        else{
            console.log('false')
        }
        
    }
        function uploadfile() {
            var blob = document.getElementById("file").files[0];
            var start = 0;
            var end;
            var index = 1;
            var filesize = blob.size;
            var filename = blob.name;
            var complete = false;
        nowUploadNums =0;
        const  totalChunks= Math.ceil(filesize / CHUNK_SIZE );
            let uploadedChunks = 0;
            let chunkRetries = {};
          function updateProgress() {
            
        document.getElementById('downloadProgress').value =Math.round((uploadedChunks / totalChunks) * 100);

          
           }

        function uploadNextChunk() {
            if (uploadedChunks >= totalChunks) {
                console.log('文件上传完成!');
                updateProgress(); // 确保进度条显示100%
                // 通知服务器所有分片都已上传,可以进行合并
                return;
            }

            const start = uploadedChunks * CHUNK_SIZE;
            const end = Math.min(start + CHUNK_SIZE, blob.size);
            const chunk = blob.slice(start, end);
            const chunkIndex = uploadedChunks;

            if (!chunkRetries[chunkIndex]) {
                chunkRetries[chunkIndex] = 0;
            }
         
       const wordArray = CryptoJS.lib.WordArray.create(chunk );
              const clienthash= CryptoJS.MD5(wordArray).toString()
            uploadChunk(chunk, chunkIndex,filename ,clienthash,complete,uploadedChunks , totalChunks).then(() => {
                uploadedChunks++;
                updateProgress(); // 更新进度条
                uploadNextChunk(); // 上传下一个分片
            }).catch((error) => {
                chunkRetries[chunkIndex]++;
                console.error(`上传分片 ${chunkIndex} 失败: ${error.message}, 重试次数: ${chunkRetries[chunkIndex]}/${MAX_RETRIES}`);
                if (chunkRetries[chunkIndex] < MAX_RETRIES) {
                    // 等待一段时间后重试上传当前分片
                    setTimeout(uploadNextChunk, 1000); // 延迟1秒重试
                } else {
                    console.error(`分片 ${chunkIndex} 上传失败,已达到最大重试次数`);
                    // 处理上传失败的情况,比如停止上传或通知用户
                }
            });
        
          }
        uploadNextChunk();
    }
           

    
    function uploadChunk(chunk, sliceIndex,filename,clienthash,complete,index,totalPieces) {
          var formData = new FormData();
          formData.append("file", chunk);
          formData.append("name_index", sliceIndex);
          formData.append("filename", filename);
      formData.append("clienthash", clienthash);
          formData.append("complete",complete);
          formData.append("process", index / totalPieces);

        return $.ajax({
            url: '/upload_filesliceprocess', // 替换为你的上传URL
            type: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            // 可以设置timeout来处理请求超时的情况
        });
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/20289.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue脚手架开发打地鼠游戏

游戏设计&#xff1a; 规划游戏的核心功能&#xff0c;如场景、随机出现的地鼠、计分系统、游戏时间限制等。简单设计游戏流程&#xff0c;包括开始界面、游戏进行中、关卡设置&#xff08;如不同关卡地鼠出现数量、游戏时间等&#xff09;、关卡闯关成功|失败、游戏结束闯关成…

Web 后端 请求与响应

一 请求响应 1. 请求&#xff08;Request&#xff09; 客户端向服务器发送的HTTP请求&#xff0c;通常包含以下内容&#xff1a; 请求行&#xff1a;HTTP方法&#xff08;GET/POST等&#xff09;、请求的URL、协议版本。 请求头&#xff08;Headers&#xff09;&#xff1a;…

Linux的基础指令和环境部署,项目部署实战(下)

目录 上一篇&#xff1a;Linxu的基础指令和环境部署&#xff0c;项目部署实战&#xff08;上&#xff09;-CSDN博客 1. 搭建Java部署环境 1.1 apt apt常用命令 列出所有的软件包 更新软件包数据库 安装软件包 移除软件包 1.2 JDK 1.2.1. 更新 1.2.2. 安装openjdk&am…

DeepSeek在linux下的安装部署与应用测试

结合上一篇文章&#xff0c;本篇文章主要讲述在Redhat linux环境下如何部署和使用DeepSeek大模型&#xff0c;主要包括ollama的安装配置、大模型的加载和应用测试。关于Open WebUI在docker的安装部署&#xff0c;Open WebUI官网也提供了完整的docker部署说明&#xff0c;大家可…

罗德与施瓦茨ZNB20,矢量网络分析仪9KHz-20GHz

罗德与施瓦茨ZNB20矢量网络分析仪9KHz-20GHz R&SZNB20矢量网络分析仪 产品型号: ZNB20 产品品牌&#xff1a;罗德与施瓦茨 R&S 产品名称: 矢量网络分析仪 频率范围&#xff1a;9kHz - 20GHz R&S ZNB 矢量网络分析仪 良好的测量速度、动态范围和操作方便性&am…

axios post请求 接收sse[eventsource]数据的

axios 接收sse数据的 axios 接收sse数据的 EventSource什么 基于 HTTP 协议实现&#xff0c;通过与服务器建立一个持续连接&#xff0c;实现了服务器向客户端推送事件数据的功能。在客户端&#xff0c;EventSource 对象通过一个 URL 发起与服务器的连接。连接成功后&#xff0…

Python----数据结构(双向链表:节点,是否为空,长度,遍历,添加,删除,查找,循环链表)

一、双向链表 1.1、概念 双向链表是一种链表数据结构&#xff0c;每个节点除了包含指向下一个节点的指针外&#xff0c;还包含指向前一个节点的指针。这种特性使得在双向链表中&#xff0c;可以从任意一个节点开始&#xff0c;向前或向后遍历链表。 1.2、特点 • 既可以从…

VScode内接入deepseek包过程(本地部署版包会)

目录 1. 首先得有vscode软件 2. 在我们的电脑本地已经部署了ollama&#xff0c;我将以qwen作为实验例子 3. 在vscode上的扩展商店下载continue 4. 下载完成后&#xff0c;依次点击添加模型 5. 在这里可以添加&#xff0c;各种各样的模型&#xff0c;选择我们的ollama 6. 选…

投资组合风险管理

投资组合风险管理 市场风险 信用风险流动性风险风险指标收益率波动率最大回撤 α \alpha α&#xff08;詹森指数&#xff09;&#xff0c; β \beta β卡玛比率月胜率上/下行捕获比夏普比率索提诺比率经风险调整的收益率&#xff08;&#x1d440;2&#xff09;特雷诺比率信息…

Mongodb数据管理

Mongodb数据管理 1.登录数据库&#xff0c;查看默认的库 [rootdb51~]# mongo> show databases; admin 0.000GB config 0.000GB local 0.000GB> use admin switched to db admin > show tables system.version > admin库&#xff1a;admin 是 MongoDB 的管理…

GTP3 大模型

GTP3 大模型 模型架构训练核心思想 GTP3 : OpenAI 在 2020 年 5 月发布 GPT-3&#xff0c;发表 Language Models are Few-Shot Learner理念&#xff1a;Few-Shot 思想 , 用少量样本微调&#xff0c;让模型更准确 参数 : 最大模型 : 1750 亿参数多头 Transformer : 96 层Head…

神经网络实验——MLP

目录 1 目的 2 方法 3 源代码 4 结果 1 目的 ①熟悉 Python 的输入输出流; ②学会使用 matplotlib进行图像可视化; ③掌握神经网络的基本原理&#xff0c;学会使用 sklearn 库中的 MLPClassifier 函数构建基础的多层感知机神经网络分类器; ④学会使用网格查找进行超参数优…

Cursor 无限续杯

最近DeepSeek官网无法访问&#xff0c;导致DeepSeekCLine绑定的API Key也无法使用了。那么&#xff0c;除了DeepSeek&#xff0c;还有没有其他好用的AI编程工具呢&#xff1f;答案当然是Cursor&#xff01;不过&#xff0c;由于各种原因一直没有用上Cursor&#xff0c;也不知道…

Windows本地部署DeepSeek

文章目录 一、准备工作1、准备服务器2、准备APP 二、部署deepseek-r11、脚本部署2、脚本部署 三、ChatBox集成 一、准备工作 1、准备服务器 本案例使用Windows电脑 2、准备APP Download Ollama Download Chatbox 二、部署deepseek-r1 1、脚本部署 双击安装完Ollama,默认…

QML 自定义矩形框Rectangle,实现四个边框自定义大小

一、自定义矩形 效果图 边框大小为&#xff1a;左2 上2 右5 下10 简单来说&#xff0c;就是定义两个矩形&#xff0c;一个在外边一个在内部&#xff1b; 再通过设置他们的边距&#xff0c;即可设置相应的边框宽度&#xff1b; 1.编码 新建空的qml文件 MyRectangle.qml im…

筛选相同项

# import os # import pandas as pd# # 文件路径&#xff0c;根据实际情况修改 # file_path_1 rC:\Users\Administrator\Desktop\python\文件1.xlsx # file_path_2 rC:\Users\Administrator\Desktop\python\文件2.xlsximport os import pandas as pd# 获取当前脚本所在的目录…

MVTEC数据集笔记

前言 网上的博客只有从论文里摘出的介绍&#xff0c;没有数据集文件详细的样子&#xff0c;下载数据集之后&#xff0c;对数据集具体的构成做一个补充的笔记。 下载链接&#xff1a;https://ai-studio-online.bj.bcebos.com/v1/7d4a3cf558254bbaaf4778ea336cb14ed8bbb96a7f2a…

Bom详解和Dom详解

Javascript的数据类型 1.BOM(浏览器对象模型)1.1window对象(1)全局作用域&#xff1a;(2)窗口属性&#xff1a;(3)弹窗和对话框&#xff1a;(4)定时器&#xff1a;(5)导航和历史&#xff1a;(6)打开和关闭窗口&#xff1a; 1.2navigator对象(1)浏览器信息属性&#xff1a;(2)浏…

Android 虚拟机与ClassLoader类加载笔记

1 Android虚拟机 在介绍Android的虚拟机之前&#xff0c;我们先来看一下JVM虚拟机之下&#xff0c;我们的class文件的字节码指令的Demo&#xff1a; public class Demo {public static void test() {int a 1;int b 2;int c a b;} } 将Demo.class文件使用命令&#xff1a…

STM32 HAL库USART串口DMA IDLE中断编程:避坑指南

HAL_UART_Receive接收最容易丢数据了,STM32 HAL库UART查询方式实例 可以考虑用中断来实现,但是HAL_UART_Receive_IT还不能直接用,容易数据丢失,实际工作中不会这样用,STM32 HAL库USART串口中断编程&#xff1a;演示数据丢失, 需要在此基础优化一下. STM32F103 HAL库USART串口…