Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
287 views
in Technique[技术] by (71.8m points)

关于前端下载的问题?

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...