上传文件块时,它们是否保证以相同的顺序接收?
When uploading file chunks are they guaranteed to be received in the same order?
Javascript前端,servicestack后端。
我正在使用最新版本的 dropzone.js 上传大型图像文件(最大 50GB)。该文件被分成许多块,服务器一个接一个地接收它们。当我收到最后一个块时,我知道我有完整的文件并且可以开始处理了。但是,如果块没有按顺序到达怎么办?一旦数据离开客户端,由于 Internet 路由,是否有可能乱序接收数据块?
服务器端(服务堆栈)在调用之间没有持久性(我知道)所以我无法计算接收到的块(至少在没有写入数据库或其他东西的情况下)。
这是我需要关心的事情吗?最好的处理方法是什么?
首先你需要知道文件块是如何发送的,以便知道如何处理它们,例如他们是否使用标准 HTTP multipart/formdata File Uploads in which case they'll be available in ServiceStack's Request.Files collection or some other way like sending raw bytes, in which case your Request DTO will need to implement IRequiresStream 来访问未序列化的原始字节。
服务器无法保证客户端将如何发送它,如果可以保证客户端仅按顺序发送块,那么服务器可以假定它始终是这样发送的,但服务器知道块可以是它可能需要支持的并发、无序和并行发送。
我个人会避免通过独立的 HTTP API 请求分块上传文件,因为它会增加大量的复杂性,但如果文件最多 50GB
那么你将需要想出一个定制的解决方案。
您将像处理任何分块数据一样处理这些块(例如,想象一下如果您必须手动将来自多个服务的响应拼接在一起)。因为文件可能很大,所以将它们存储在内存中(如 ConcurrentDictionary)不是一种选择。如果您可以访问云存储服务,您可能希望将临时块上传到那里,否则您需要将它们存储在磁盘上。理想情况下,您的解决方案应利用文件将保留的最终数据存储解决方案。
否则,一个天真的解决方案是,在客户端上传客户端需要发送的文件以及需要发送的块索引和总块数之前,服务器应该生成一个唯一的密钥,如 Guid。然后,每个服务都会将该块直接写入磁盘,首先是在临时文件路径 (Path.GetTempFileName()
) 中,然后在写入文件后将其移动到 /uploads/{unique-id}/{chunk-index}.dat
.
等格式
在每个块上传请求结束时,您可以检查您的 /uploads/{unique-id}/
目录是否包含所有块,如果它确实开始拼接它并创建单个文件的过程。尽管更稳健的方法是让客户端在完成所有块的上传后启动文件拼接,但如果拼接失败,您可以手动调用再次拼接文件的服务,而不需要让客户端 re-upload 文件。
Javascript前端,servicestack后端。
我正在使用最新版本的 dropzone.js 上传大型图像文件(最大 50GB)。该文件被分成许多块,服务器一个接一个地接收它们。当我收到最后一个块时,我知道我有完整的文件并且可以开始处理了。但是,如果块没有按顺序到达怎么办?一旦数据离开客户端,由于 Internet 路由,是否有可能乱序接收数据块?
服务器端(服务堆栈)在调用之间没有持久性(我知道)所以我无法计算接收到的块(至少在没有写入数据库或其他东西的情况下)。
这是我需要关心的事情吗?最好的处理方法是什么?
首先你需要知道文件块是如何发送的,以便知道如何处理它们,例如他们是否使用标准 HTTP multipart/formdata File Uploads in which case they'll be available in ServiceStack's Request.Files collection or some other way like sending raw bytes, in which case your Request DTO will need to implement IRequiresStream 来访问未序列化的原始字节。
服务器无法保证客户端将如何发送它,如果可以保证客户端仅按顺序发送块,那么服务器可以假定它始终是这样发送的,但服务器知道块可以是它可能需要支持的并发、无序和并行发送。
我个人会避免通过独立的 HTTP API 请求分块上传文件,因为它会增加大量的复杂性,但如果文件最多 50GB
那么你将需要想出一个定制的解决方案。
您将像处理任何分块数据一样处理这些块(例如,想象一下如果您必须手动将来自多个服务的响应拼接在一起)。因为文件可能很大,所以将它们存储在内存中(如 ConcurrentDictionary)不是一种选择。如果您可以访问云存储服务,您可能希望将临时块上传到那里,否则您需要将它们存储在磁盘上。理想情况下,您的解决方案应利用文件将保留的最终数据存储解决方案。
否则,一个天真的解决方案是,在客户端上传客户端需要发送的文件以及需要发送的块索引和总块数之前,服务器应该生成一个唯一的密钥,如 Guid。然后,每个服务都会将该块直接写入磁盘,首先是在临时文件路径 (Path.GetTempFileName()
) 中,然后在写入文件后将其移动到 /uploads/{unique-id}/{chunk-index}.dat
.
在每个块上传请求结束时,您可以检查您的 /uploads/{unique-id}/
目录是否包含所有块,如果它确实开始拼接它并创建单个文件的过程。尽管更稳健的方法是让客户端在完成所有块的上传后启动文件拼接,但如果拼接失败,您可以手动调用再次拼接文件的服务,而不需要让客户端 re-upload 文件。