前端实现断点下载

背景:当下载一个很大的文件时,如果下载到一半暂停,如果继续下载呢?断点下载就是解决这个问题的。

什么是断点下载?

所谓断点下载就是可以一部分一部分的下载,不用一次性把文件数据全部拿到。

涉及到的主要HTTP消息头

通用首部请求头响应头实体头
Status CodeRange:请求数据范围

Accept-Ranges:标识自身支持范围请求

Content-Range:一个数据片段在整个文件中的位置。

ETag:资源特定版本标识符

Last-Modified:资源修改日期时间

Content-MD5

//实体编码摘要

其他可能用到的消息头:

If-Range 请求头字段用来使得 Range 头字段在一定条件下起作用

If-None-Match:如果ETag不匹配

If-Match:如果ETag匹配

HTTP HEAD方法(因为安全策略,浏览器中通过XMLHttpRequest只能获取部分头部信息)

请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致。 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源。

代码实现

1、服务端要支持范围请求,响应信息中的Accept-Ranges: bytes,表示接收以字节为单位的范围请求

2、在发送的请求信息中要加上范围请求信息,Range: bytes=0-100请求头信息,表示请求0-100字节的数据

3、通过HEAD方法来获取文件的大小

getContentLength(url) {
    return new Promise(resolve => {
        const xhr = new XMLHttpRequest()
        xhr.open('HEAD', url)
        xhr.onload = function () {
            resolve(xhr.getResponseHeader('content-length') || 0)
        }
        xhr.send()
    })
}

4、将文件按照一定的大小分块请求

import { saveAs } from 'file-saver/FileSaver' //安装依赖包,用于保存文件
function partDownload(url, start, end, contentLength, partLength = 1000) {
    let xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.responseType = 'arraybuffer' 
    // arraybuffer blob,指定arraybuffer类型便于进行数据处理,具体看使用情况
    xhr.setRequestHeader('Range', `bytes=${start}-${end}`)
    xhr.onload = function () {
        if (xhr.status === 200) {
            //将arraybuffer转成blob
            saveAs(new Blob([xhr.response]), '文件名.xlsx')
        }

        if (xhr.status === 206) {
            let endLength = end + partLength
            if (endLength > contentLength) {
                endLength = contentLength
            }
            partDownload(url, end + 1, endLength, contentLength)
        }

        if (xhr.status === 416) {
            console.log('416', xhr.response)
        }
    }
    xhr.onerror = function () {}
    xhr.send({})
}

5、完整代码

getContentLength(url).then(length => {
    partDownload(url, 0, 100, length)
})

前端实现文件断点续传或断点下载通常通过创建一个可以暂停、恢复和继续下载的机制来完成,这通常结合了HTML5的`fetch` API或者`XMLHttpRequest`(XHR)。以下是基本步骤: 1. **创建进度条**:首先,你需要一个显示下载进度的元素,如`<progress>`标签。 2. **分片下载**:将大文件分割成小块(也称为"分块上传"),这样可以设置下载任务为一系列请求,每个请求处理一部分数据。如果你有一个大文件,比如`fileSize`,你可以设置每块的大小为`chunkSize`。 3. **开始下载**:初始化一个下载任务,每次发送一个HTTP请求获取文件的一部分,并更新进度条。可以使用`fetch`的`range`头来指定只请求特定范围的数据,这样浏览器会从上次停止的位置开始下载。 ```javascript async function downloadFile(url, chunkSize) { let totalSize = await getTotalFileSize(url); let startByte = 0; const progress = document.querySelector('#download-progress'); const xhr = new XMLHttpRequest(); while (startByte < totalSize) { xhr.open('GET', url + `?offset=${startByte}&length=${chunkSize}`); xhr.responseType = 'arraybuffer'; xhr.onprogress = function(e) { if (e.lengthComputable) { progress.value = Math.round((startByte + e.loaded) / totalSize * 100); } }; xhr.onload = function() { startByte += xhr.responseText.byteLength; }; xhr.send(); // 如果需要暂停和恢复,可以在适当的地方添加相应逻辑 } } ``` 4. **暂停和恢复**:如果支持,可以通过保存当前下载的进度信息(例如,最后一次请求的起始位置和总长度)并在用户需要时恢复下载。这通常涉及到存储用户的会话状态或使用cookie。 5. **错误处理**:记得处理可能出现的网络错误和文件不可用的情况,提供友好的用户反馈。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wl_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值