断点续传补充--手动暂停上传

2 篇文章 0 订阅
2 篇文章 0 订阅

断点续传补充–手动暂停上传

前文链接:点击此链接,从头观看断点续传内容

前文提到大文件切片上传以及断点续传,但是这里我们不能够手动暂停切片上传,停止不了ajax的发送。这篇文章用于实现这个功能。
网上提到停止的ajax需要使用abort()函数,但是基于我上传的方式,abort不能够完全立即停止,所以我才用setinterval和clearinterval;

前端代码:index.html

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.10.0/js/md5.min.js"></script>
    <!-- <link rel="stylesheet" type="text/css" href="./webupload/bootstrap/css/bootstrap.min.css"> -->
</head>
<style>

</style>

<body>
    <div id="fileUploadContainer">
        <select style="width: 150px;float: left;" class="custom-select custom-select-lg mb-3" id="selected"
            onchange="changeChoose()">
            <option selected value="file">选择文件</option>
            <option value="folder">选择文件夹</option>
        </select>
        <div style="width: auto;float: left;">
            <input type="file" multiple class="file uploadfile" id="file" value="选择文件" />
            <input type="file" webkitdirectory class="folder uploadfile" id="folder" value="选择文件夹"
                style="display: none;" />
        </div>
        <progress id="progress" max="100" value="0"></progress>
        <div id="uploadStatus" class="webuploader-pick" style="float: left; margin-right: 10px" status="upload"
            onclick="changeStatus(this)">上传</div>
    </div>
    <script> 
        var timer;
        var chunkSize = 10 * 1024 * 1024;
        var start = 0;
        var index = 0;
        var fileTotalSize = 0;    
        // 设定是上传文件夹还是文件
        function changeChoose() {
            var obj = document.getElementById("selected"); //定位id
            var index = obj.selectedIndex; // 选中索引
            var text = obj.options[index].text; // 选中文本
            var value = obj.options[index].value; // 选中值
            if (value == 'file') {
                document.getElementById('file').style.display = 'block';
                document.getElementById('folder').style.display = 'none';
            }
            if (value == 'folder') {
                document.getElementById('file').style.display = 'none';
                document.getElementById('folder').style.display = 'block';
            }
        }
        //继续上传和暂停上传
        function changeStatus(e) {
            var status = document.getElementById('uploadStatus').getAttribute('status');
            if (status == "upload") {
                document.getElementById('uploadStatus').innerHTML = "暂停上传";
                document.getElementById('uploadStatus').setAttribute("status", "suspend");
                upload();
            }
            else {
                document.getElementById('uploadStatus').innerHTML = "继续上传";
                document.getElementById('uploadStatus').setAttribute("status", "upload"); 
                clearInterval(timer);           
            }
        }
        function upload() {
            let fileObj = document.getElementById('file').files[0];
            let fd = new FormData();
            var md5Val = md5(fileObj.name);
            fileTotalSize = fileObj.size;
            fd.append('md5', md5Val);
            fd.append('fileTotalSize', fileObj.size);
            fd.append('filename', fileObj.name);
            // 判断文件是否存在
            timer = setInterval(test,1000,fd);
        }
        function test(fd){
            ajax('/file/isExist', 'POST', fd, isExist)
        }
        function isExist(res) {
            var result = JSON.parse(res);
            if (result.isFileExist == 'isExist') {
                alert('文件存在,请改变名称或者上传其他文件!');
                return;
            } else {
                if (result.chunk == 0) {
                    start = 0;
                    index = 0;
                } else {
                    start = result.chunk * chunkSize;
                    index = result.chunk;
                }

                uploadChunk(chunkSize, start, index);
                
            }
        }   
        function uploadChunk(chunkSize, start, index) {
            let fileObj = document.getElementById('file').files[0];
            // 文件名md5
            var md5Val = md5(fileObj.name);

            // 上传完成
            if (start >= fileObj.size) {
                let fd = new FormData();
                fd.append('md5', md5Val);
                fd.append('filename', fileObj.name);

                ajax('/file/merge', 'POST', fd, mergeChunk);
                clearInterval(timer);
                document.getElementById('file').files[0] = "";
                return;
            }

            // 获取文件块的终止字节
            let end = (start + chunkSize > fileObj.size) ? fileObj.size : (start + chunkSize);
            // 将文件切块上传
            let fd = new FormData();
            fd.append('file', fileObj.slice(start, end));
            fd.append('md5', md5Val);
            fd.append('chunk', index);

            var xmlhttp = new XMLHttpRequest();
            xmlhttp.open('POST', 'http://127.0.0.1:5000/isUpload', true);
            xmlhttp.onload = function () {
                if (this.readyState == 4 && this.status == 200) {
                    // 上传一块完成后修改进度条信息,然后上传下一块
                    let progress = document.getElementById('progress');
                    progress.max = fileObj.size;
                    progress.value = end;
                }
            }
            xmlhttp.send(fd);
        }   
        function mergeChunk(res) {
            console.log('文件生成成功!');
        }
        //ajax model
        function ajax(url, method, msg, fn, id, innerHTMLId) {
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            } else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    fn(xmlhttp.responseText, url, id, innerHTMLId)
                }
            }
            xmlhttp.open(method, url, true);
            xmlhttp.send(msg);
        }
    </script>
</body>

</html>

后端代码:upload.py

from flask import Flask,session,request,jsonify,abort
from flask.templating import render_template
from flask_cors import CORS
import hashlib,os
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
import threading
import time
import inspect
import ctypes


app=Flask(__name__)
CORS(app, supports_credentials=True)

threadArr = {}
chunkSize = 10 * 1024 * 1024;

@app.route("/")
def home():
    return render_template('index.html')

@app.route("/isUpload",methods = ['GET','POST'])
def isUpload():
    if request.method == 'POST':
        # 存储切片
        md5Val = request.form.get('md5')  # 获取文件的唯一标识符
        chunk = request.form.get('chunk', 0)  # 获取该分片在所有分片中的序号
        filename = '%s%s' % (md5Val, chunk)  # 构造该分片的唯一标识符
        upload_file = request.files['file']
        upload_file.save('./chunk/%s' % filename)  # 保存分片到本地

    return 'isUpload'



@app.route('/file/isExist', methods=['POST'])
def isExist():
    target_filename = request.form.get('filename')
    md5Val = request.form.get('md5')
    fileTotalSize = request.form.get('fileTotalSize')
    chunk = 0  # 分片序号
    chunkTotalSize = 0

    result = {}
    isFileExist='notExist'
    if os.path.exists('./uploadfile/%s' % target_filename):
        isFileExist='isExist'
    else:
        isFileExist='notExist'
    

    while True:
        try:
            filename = './chunk/%s%d' % (md5Val, chunk)
            if os.path.exists(filename):
                chunk += 1
                chunkTotalSize += os.path.getsize(filename)
            else:
                break
        except IOError as msg:
            break

    result['isFileExist'] = isFileExist
    result['chunk'] = chunk
    result['chunkTotalSize'] = chunkTotalSize
    print(result)
    return result    

@app.route('/file/merge', methods=['POST'])
def upload_success():  # 按序读出分片内容,并写入新文件
    md5Val = request.form.get('md5')  # 获取文件的唯一标识符
    target_filename = request.form.get('filename')  # 获取该分片在所有分片中的序号
    chunk = 0  # 分片序号
    with open('./uploadfile/%s' % target_filename, 'wb') as target_file:  # 创建新文件
        while True:
            try:
                filename = './chunk/%s%d' % (md5Val, chunk)
                source_file = open(filename, 'rb')  # 按序打开每个分片
                target_file.write(source_file.read())  # 读取分片内容写入新文件
                source_file.close()
            except IOError as msg:
                break

            chunk += 1
            os.remove(filename)  # 删除该分片,节约空间

    return '文件上传成功!'


if __name__=='__main__':
    app.run(debug=True)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值