Skip to content

大文件传输

大文件(如 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 头"。面试高频。