当下载文件以 HTTP 状态行开头时
不要把 HTTP 响应分帧写进下载产物,也不要把代理套接字收到的每个字节都复制到输出文件。
如果一份本应是 PDF 或电子表格的文件以 HTTP/1.1 200 OK 开头,说明下载器保存的是原始响应,而不是产物本身。这个示意响应只有四个字节的内容:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
4
DATA
0
产物是 DATA。状态行、首部、大小标记和结束结构都属于 HTTP。删除固定数量的字节并不安全,因为首部长度各不相同。即使复制第一个空行之后的所有内容,仍会留下分块分帧;而且信息性响应可能出现在最终响应之前。
对于正常下载,应当用 HTTP 客户端提供的响应体接口取代“从原始套接字复制到文件”的做法。配置其代理,校验最终状态,并将响应体流式写入临时输出。消息分帧由客户端处理:长度定界、分块(chunked)和连接定界的响应体需要不同的解析方式。
内容编码是另一层。请依据客户端文档化的行为,决定你需要的是解码后的产物字节,还是明确请求的原始内容。压缩后的字节并不自动意味着代理损坏。
如果应用必须保留套接字层代码,那么这些解析规则以及读写处理都由它自己负责。写入时只写读取实际返回的字节数,而不是缓冲区容量,并处理部分写入。否则,缓冲区中的陈旧内容可能损坏即使已正确提取的响应体。
HTTPS 需要的不只是剥掉 CONNECT 响应:隧道成功建立后,还要建立到目标的 TLS,然后解析内层 HTTP 响应。代理首部之后的加密字节并不是可下载的文件。
把失败或不完整的输出留在临时名称下。只有在传输和产物检查都成功之后才发布;文件非空并不能证明下载完整。