问答

关于前端下载的问题?

作者:admin 2021-06-10 我要评论

后台的文件是按照流的形式传递给前端, 如果文件太大,刷新页面,前端的下载请求,就没了 导致下载失败 我看chrome的下载,好像是在后台进行的,跟页面的刷新没...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

后台的文件是按照流的形式传递给前端,
如果文件太大,刷新页面,前端的下载请求,就没了
导致下载失败

我看chrome的下载,好像是在后台进行的,跟页面的刷新没什么关系,
如何解决刷新页面导致下载失败的问题尼

###

HTTP断点下载功能

1).HTTP 请求头 Range
Range: bytes=start-end  
Range: bytes=10- :第10个字节及最后个字节的数据  
Range: bytes=40-100 :第40个字节到第100个字节之间的数据.

示例:

表示从第0个字节开始下载

conn.addRequestProperty(“range”, “bytes=” + 0 + “-“);

注意:若支持range分段下载,服务端需返回206状态码。
nginx默认支持range分段下载。
tomcat默认也支持range分段下载

2).响应头

Content-Range

Content-Range: bytes 0-10/3103  
这个表示,服务器响应了前(0-10)个字节的数据,该资源一共有(3103)个字节大小。

然后要记录当前已经下载了多少字节。

小封装

import * as path from 'path';

import * as fs from 'fs';

import axios from 'axios';

  

const { CancelToken } = axios;

class StreamDownload {

constructor() {

// 初始化

this.initialize();

}

  

// 下载函数

async downloadFile(downloadFileName, patchUrl, baseDir, receivedBytes, callback) {

this.downloadCallback = callback; // 注册回调函数

this.downloadFileName = downloadFileName;// 下载名字

this.baseDir = baseDir;

this.patchUrl = patchUrl;

this.receivedBytes = receivedBytes || 0;

try {

const req = await axios({

method: 'GET',

url: patchUrl,

responseType: 'stream',

headers: {

Range: `bytes=${this.receivedBytes}-`,

},

cancelToken: this.source.token,

});

const out = fs.createWriteStream(path.join(this.baseDir, this.downloadFileName), {

start: this.receivedBytes,

flags: this.receivedBytes > 0 ? 'r+' : 'w',

});

req.data.pipe(out);

this.totalBytes = parseInt(req.data.headers['content-length'], 10);

fs.writeFile(path.join(this.baseDir, 'info'), JSON.stringify({ url: this.patchUrl, receivedBytes: this.receivedBytes, totalBytes: this.totalBytes }), () => {});// 记录一下当前下载信息

req.data.on('data', (chunk) => {

// 更新下载的文件块字节大小

this.receivedBytes += chunk.length;

this.showProgress(this.receivedBytes, this.totalBytes);

});

// // 读取返回数据

req.data.on('end', () => {

console.log('结束了');

this.downloadCallback('finished', '');

if (this.receivedBytes >= this.totalBytes) {

fs.writeFile(path.join(this.baseDir, 'info'), JSON.stringify({ url: this.patchUrl, receivedBytes: this.receivedBytes, totalBytes: this.totalBytes }), () => {});// 记录一下当前下载信息

}

this.initialize();

});

} catch (error) {

console.log(error);

this.downloadCallback('error', '');

}

}

  

// 初始化

initialize() {

this.baseDir = '';

this.patchUrl = '';

this.downloadFileName = ''; // 下载文件名称,也可以从外部传进来

this.downloadCallback = null;// //回调函数

this.totalBytes = null;// 总字节

this.receivedBytes = 0;// 已经接受的字节

this.source = CancelToken.source();

}

  

// 下载进度

showProgress(received, total) {

const percentage = Number(((received * 100) / total).toFixed(1));

// 用回调显示到界面上

this.downloadCallback('progress', percentage);

}

  

cancelToken() {

fs.writeFile(path.join(this.baseDir, 'info'), JSON.stringify({ url: this.patchUrl, receivedBytes: this.receivedBytes, totalBytes: this.totalBytes }), () => {});// 记录一下当前下载信息

this.source.cancel('Operation canceled by the user.');

}

}

  

export default new StreamDownload();
###

location = 'http://xxxxxx/xxx/xxx.avi'。
这就是利用后台的nginx或者其他的web静态服务器提供的下载能力,与页面无关。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 关于前端下载的问题?

    关于前端下载的问题?

  • idea的maven打包问题

    idea的maven打包问题

  • 本机测试udp丢包问题

    本机测试udp丢包问题

  • 请问路径一样的path, 为什么用了stroke

    请问路径一样的path, 为什么用了stroke

腾讯云代理商
海外云服务器