Appearance
大文件传输
大文件(如 1GB 视频)必须使用 request 模块代理传输,否则应用切后台会被断网。
1. 大文件传输方案对比
| 方案 | 适用场景 | 后台保活 | 说明 |
|---|---|---|---|
| http.request | 小文件(< 100MB) | ❌ 切后台断网 | 普通 HTTP 请求 |
| request 代理 | 大文件(> 100MB) | ✅ 后台代理 | 推荐 |
| Worker 下载 | 中等文件 | ⚠️ 有限 | 需申请后台模式 |
2. request 模块代理下载
2.1 下载大文件
typescript
import { request } from '@kit.NetworkKit'
class DownloadManager {
private downloadTask: request.Request | null = null
// 下载大文件
async download(url: string, filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
let requestTask = request.createRequest({
url: url,
method: request.RequestMethod.GET,
headers: {
'Authorization': 'Bearer xxx'
}
})
// 设置回调
requestTask.on('progress', (progress: request.ProgressEvent) => {
console.log(`下载进度: ${progress.progress}%`)
this.updateProgress(progress.progress)
})
requestTask.on('complete', (data: request.DownloadCompleteData) => {
console.log('下载完成')
resolve(data.filePath)
})
requestTask.on('error', (err: request.RequestError) => {
console.error('下载失败:', err.message)
reject(err)
})
// 开始下载
requestTask.downloadTo({
filePath: filePath, // 存储路径
resumeSupport: true // 支持断点续传
}).catch((err) => {
reject(err)
})
})
}
// 取消下载
cancel(): void {
if (this.downloadTask) {
this.downloadTask.cancel()
}
}
}3. 上传大文件
3.1 上传实现
typescript
class UploadManager {
async upload(filePath: string, uploadUrl: string): Promise<string> {
let requestTask = request.createRequest({
url: uploadUrl,
method: request.RequestMethod.POST,
headers: {
'Content-Type': 'application/octet-stream'
}
})
// 进度回调
requestTask.on('progress', (progress: request.ProgressEvent) => {
console.log(`上传进度: ${progress.progress}%`)
})
return new Promise((resolve, reject) => {
requestTask.on('complete', (data: request.UploadCompleteData) => {
console.log('上传完成:', data.result)
resolve(data.result as string)
})
requestTask.on('error', (err) => {
reject(err)
})
// 上传文件
requestTask.uploadFrom({
filePath: filePath
})
})
}
}4. 断点续传
4.1 实现断点续传
typescript
class ResumableDownloadManager {
private downloadedSize: number = 0
async resumeDownload(url: string, filePath: string): Promise<void> {
// 检查已下载的部分
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE)
this.downloadedSize = fs.lstatSync(file.fd).size
fs.closeSync(file)
let requestTask = request.createRequest({
url: url,
method: request.RequestMethod.GET,
headers: {
// Range: 请求已下载部分之后的内容
'Range': `bytes=${this.downloadedSize}-`
}
})
requestTask.on('progress', (progress: request.ProgressEvent) => {
console.log(`下载进度: ${progress.progress}%`)
})
requestTask.on('complete', () => {
console.log('下载完成')
})
requestTask.downloadTo({
filePath: filePath,
resumeSupport: true,
resumeFrom: this.downloadedSize // 从已下载位置继续
})
}
}5. 面试高频考点
Q1: 如何传输大文件(如 1GB 视频)?
回答:必须使用 request 模块(上传下载代理服务),由系统服务在后台代理传输,否则应用切后台会被断网。
Q2: 为什么普通 http 不能传大文件?
回答:普通 http 请求切后台会被系统断开网络连接。request 模块由系统服务代理,支持后台传输和断点续传。
🐱 小猫提示:大文件传输记住 "request 代理、后台保活、断点续传、Range 头"。面试高频。