Open xvno opened 2 years ago
// controller/Foo.ts
async download() {
const filePath = '/path/to/file';
this.ctx.attachment(filePath);
this.ctx.set('Content-Type', 'application/octet-stream');
this.ctx.body = fs.createReadStream(filePath);
}
仅需这样实现,即可实现下载,但这样实现的下载会发现没有下载进度条,也不知道还有多久下载完。原因 HTTP 返回头里没有 Content-Length。
// controller/Foo.ts
async download() {
const filePath = '/path/to/file';
const fileSize = (await promisify(stat)(filePath)).size.toString();
this.ctx.attachment(filePath);
this.ctx.set('Content-Length', fileSize);
this.ctx.set('Content-Type', 'application/octet-stream');
this.ctx.body = createReadStream(filePath);
}
在服务端我们需要处理客户端请求头中的 Range 字段,同时再返回 Content-Range。
利用Koa生态的koa-range来实现: koa-range
先创建一个中间件:
// app/middleware/range.ts
import * as KoaRange from 'koa-range';
export default function RangeMiddleware() {
return KoaRange;
}
然后在配置中启用它:
// config/config.default.ts
import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg';
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
config.middleware = ['range'];
return config;
};
使用 wget 测试一下,加入 -c 就可以了:
wget -c http://domain/path/to/file.tar.gz
file.tar.gz 27%[++========> ] 1.28G 1.52MB/s in 12m 39s
Refs