你有多少次试图上传一个大文件,却知道因为网络问题而失败了!当你再次上传文件时,却从头开始。当你再次上传文件时,上传又从头开始了:(。一点都不酷。这就是可恢复文件上传器的用武之地。
可恢复的文件上传器允许文件上传从停止的地方开始,而不是重新上传整个文件。
在本系列教程中,我们将学习如何使用tus协议在Go中创建一个可恢复文件上传服务器和客户端。本教程不是tus协议的精确实现,而是一个简化版本。本教程是自给自足的,可以用Go创建一个可恢复的文件上传器。我们将在接下来的教程中不断改进这个上传器,使其完全兼容tus。
本教程有以下几个部分
- Tus协议
- 创建文件的POST请求
- 更新文件的PATCH请求
- HEAD请求,获取当前文件的偏移量
Tus协议
tus协议相当简单,tus的最大卖点是它在HTTP之上工作。让我们先了解一下tus协议是如何工作的。
Tus协议需要三种http方法,即POST、PATCH和HEAD。最好用一个例子来理解tus协议。
让我们以上传一个大小为250字节的文件为例。接下来的部分将解释使用tus协议上传文件所需的http调用顺序。
创建文件的POST请求
这是第一步。客户端向服务器发送一个带有文件上传长度(大小)的POST 请求。服务器会创建一个新的文件,并回复文件的位置。
请求
POST /files HTTP/1.1
Host: localhost:8080
Content-Length: 0
Upload-Length: 250
在上面的请求中,我们向URLlocalhost:8080/files 发送一个POST请求,以创建一个具有Upload-length 250字节的文件。Upload-length 代表整个文件的大小。由于该请求没有信息体,Content-Length 字段为零。
服务器创建了该文件并返回以下响应。
响应
HTTP/1.1 201 Created
Location: localhost:8080/files/12
Location 头提供了创建文件的位置。在我们的例子中,它是localhost:8080/files/12
更新文件的PATCH请求
补丁请求用于在偏移量Upload-Offset ,向文件写入字节。每个补丁请求都应该包含一个Upload-Offset 字段,表明正在上传的文件数据的当前偏移量。
在我们的例子中,由于我们刚刚创建了一个新的文件并开始向文件上传数据,客户端发送了一个PATCH 请求,其中Upload-Offset 为0。请注意,文件的偏移量是以0为基础的。文件的第一个字节位于偏移量0。
请求
PATCH /files/12 HTTP/1.1
Host: localhost:8080
Content-Length: 250
Upload-Offset: 0
[250 bytes of the file]
在上面的请求中,Content-Length 字段是250,因为我们要上传一个250字节的文件。Upload-Offset 是0,表明服务器应该在文件的第1字节处写入请求的内容。
服务器将用一个204 No Content 头来响应,表明请求是成功的。对PATCH 请求的响应应包含Upload-Offset 字段,表明要上传的下一个字节。在这种情况下,Upload-Offset 字段将是250 ,表明服务器已经收到了整个文件,上传已经完成。
响应
HTTP/1.1 204 No Content
Upload-Offset: 250
服务器的上述响应表明,上传已经成功完成,因为Upload-Offset 等于Upload-Length 250 。
HEAD请求获得当前文件的偏移量
上面的补丁请求成功完成,没有任何网络问题,文件被完全上传。
如果在上传文件的过程中出现了网络问题,中途上传失败怎么办。客户端不应该再次上传整个文件,而应该从失败的字节开始上传文件。这就是HEAD请求的帮助所在。
假设文件上传请求在上传了100 字节后断开了连接。客户端需要向服务器发送一个HEAD 请求,以获得文件的当前Upload-Offset ,从而知道有多少字节已经被上传,还有多少字节有待上传。
请求
HEAD /files/12 HTTP/1.1
Host: localhost:8080
响应
HTTP/1.1 200 OK
Upload-Offset: 100
服务器响应的是上传偏移量100,表示客户端必须从偏移量100开始重新上传。注意,对头请求的响应不包含信息体。它只包含一个头。
客户端用这个上传偏移量发送一个PATCH请求,请求正文包含剩余的150字节
250(文件大小)-100(上传偏移量)=150剩余字节
请求
PATCH /files/12 HTTP/1.1
Host: localhost:8080
Content-Length: 150
Upload-Offset: 100
[Remaining 150 bytes]
响应
HTTP/1.1 204 No Content
Upload-Offset: 250
服务器以204 状态和Upload-Offset: 250 等于Upload-Length 做出响应,表明文件已经完全上传。
如果在上传过程中请求再次失败,客户应该发送一个HEAD ,然后是PATCH 。
要点是不断调用HEAD ,以了解当前的Upload-Offset ,然后是PATCH ,直到服务器响应一个等于Upload-Length 的Upload-Offset 。