Web客户端能否实现向Google Cloud Storage的断点续传?
嘿,你完全没搞错——单纯靠FileReader确实搞不定大文件的断点续传,但这事儿根本不需要死磕FileReader,Web API和GCS本身就有专门的方案支持!
为什么FileReader不适合?
FileReader的核心是把文件内容读进内存(转成Blob/ArrayBuffer),大文件这么搞直接会爆内存,而且它没有原生的“暂停/续传”机制,一旦中断就得从头读,完全不符合断点续传的需求。所以你觉得它不行,是完全正确的判断。
实现断点续传的核心工具
要搞定这个需求,你需要两个关键东西:
File.slice()API:这是Web原生API,能把大文件切成任意大小的小块(Blob对象),不用把整个文件读进内存。- GCS的可恢复上传(Resumable Uploads)接口:GCS专门为大文件上传设计的特性,支持分片上传、断点续传,还能合并分片。
具体实现步骤
初始化上传会话
先给GCS发送一个POST请求,带上文件的元数据(比如存储桶名、文件名),GCS会返回一个会话URL。这个URL是后续所有分片上传、进度查询、完成上传的唯一入口,要保存好。分片切割文件
用File.slice(startByte, endByte)把大文件切成固定大小的块(GCS要求每个分片至少5MB,最后一块可以更小)。比如每次切5MB:const chunkSize = 5 * 1024 * 1024; // 5MB const start = 0; const end = Math.min(file.size, start + chunkSize); const chunk = file.slice(start, end);逐个上传分片
对每个分片,用PUT请求发到会话URL,请求头里必须加Content-Range,标明当前分片在整个文件中的范围:const headers = new Headers(); headers.append('Content-Range', `bytes ${start}-${end-1}/${file.size}`); const response = await fetch(sessionUrl, { method: 'PUT', headers: headers, body: chunk });上传成功后,记录当前已经上传到的字节位置(比如存在
localStorage或者IndexedDB里),这样下次中断后就能从这个位置继续。处理断点续传
如果上传中断了,下次打开页面时,先从存储的位置读取上次的进度,然后从那个位置开始切割文件、上传分片就行。甚至可以先发送一个GET请求到会话URL,GCS会返回当前已经上传的字节范围,帮你确认进度。完成上传
所有分片都上传成功后,发送一个空的PUT请求到会话URL,GCS就会把所有分片合并成完整的文件。
简化操作的小技巧
不用自己写底层的请求逻辑,Google官方有浏览器端的SDK适配版,或者第三方封装库,这些工具已经把分片、断点续传、错误重试的逻辑都做好了,直接调用就行。
关键注意点
- GCS要求除了最后一个分片,其他分片大小至少5MB,不然会报错。
- 会话URL的有效期是7天,要是超过时间没完成上传,就得重新初始化会话。
- 上传过程中可以随时发送GET请求到会话URL,查询当前的上传进度,避免本地记录和GCS状态不一致。
总结一下:你之前觉得FileReader不行是对的,但断点续传的核心是分片切割+GCS的可恢复上传接口,和FileReader关系不大——完全不用把整个文件读进内存,直接切分片上传就行!
内容的提问来源于stack exchange,提问作者Leo

