文件分片上传 python

embedded/2025/2/22 21:33:07/

服务端功能

上传分片保存

@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.ppmy.cn/embedded/164444.html

相关文章

第4章 信息系统架构(五)

4.7 安全架构 安全保障以风险和策略为基础&#xff0c;在信息系统的整个生命周期中&#xff0c;安全保障应包括技术、管理、人员和工程过程的整体安全&#xff0c;以及相关组织机构的健全等。 4.7.1 安全威胁 常见的威胁有&#xff1a; 4.7.2 定义和范围 安全性体现在信息系…

爬虫第七篇数据爬取及解析

这篇博客旨在分享学习过程中的心得和体会&#xff0c;如果有错误请指出&#xff0c;感谢大家。 经过前面的学习&#xff0c;那么我们也就进入了数据爬取的阶段&#xff0c;大家跟着我的步伐一起来学习一下&#xff0c;爬虫的数据爬取与数据解析&#xff08;本篇主要针对于带有…

深入剖析Spring MVC

一、Spring MVC 概述 1. 什么是 Spring MVC&#xff1f; Spring MVC 是基于 Spring 框架的 Web 框架&#xff0c;它实现了 MVC 设计模式&#xff0c;将应用程序分为三个核心部分&#xff1a; Model&#xff1a;封装应用程序的数据和业务逻辑。 View&#xff1a;负责渲染数据…

AI到底能做些什么:详细产品功能对比

1. 引言 人工智能&#xff08;AI&#xff09;作为当今科技领域的热门话题&#xff0c;已经在多个行业中展现出巨大的潜力。从自然语言处理到计算机视觉&#xff0c;从语音识别到自动化机器人&#xff0c;AI的应用范围广泛且深入。本文将详细探讨AI的核心功能、在各行业的应用、…

低代码技术在医院的应用与思考

近年来&#xff0c;低代码这一概念在医疗信息化领域频繁出现。那么&#xff0c;低代码究竟是什么&#xff1f;它因何而生&#xff1f;在医院信息系统建设与运维中&#xff0c;低代码技术又有哪些适用的应用场景&#xff1f;对于用户而言&#xff0c;低代码技术又存在哪些有待改…

idea 部署 AJ-Report 启动的注意事项

AJ-Report 入门参考&#xff1a; AJ-Report 初学(入门教程) gitee 下载&#xff1a;https://gitee.com/anji-plus/report/releases 根据上面提供的 gitee 下载链接&#xff0c;点击直接下载 最上面的就是最新版本的&#xff0c;旧版本往下拉就可以找到&#xff0c;有三个下载…

免费deepseek的API获取教程及将API接入word或WPS中

免费deepseek的API获取教程: 1 火山方舟 https://console.volcengine.com/中注册 填写邀请码&#xff1a;WGDGUTTL 即可获取3250万R1模型tokens 或硅基流动 https://cloud.siliconflow.cn/中注册时填写邀请码&#xff1a;GAejkK6X即可获取2000 万 Tokens; 2 按照图中步骤进行…

Vue Axios

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue 使用 - Axios 目录 Axios 请求方法 功能 安装 使用CDN 引入axios 使用axios 赋值 总结 Axios Axios&#xff0c;基于 Promise 的 HTTP 客户端&#xff0c;可以工作于浏览器中&#xff0c;也可以在 node.js 中使用…