上传文件块时,是否保证它们以相同的顺序被接收?

时间:2019-07-18 23:23:26

标签: servicestack dropzone.js

JavaScript前端,服务栈后端。

我正在使用最新版本的dropzone.js上传较大的图像文件(最大50GB)。该文件分为许多块,服务器一一接收。当我收到最后一个块时,我知道我拥有完整的文件,可以开始处理了。但是,如果块没有按顺序到达怎么办?一旦数据离开客户端,由于互联网路由,是否有可能乱码接收数据块?

服务器端(服务栈)在调用之间(我知道)没有持久性,因此我无法计算接收到的块(至少在不写入数据库或其他内容的情况下)。

这是我需要关注的事情,什么是最好的处理方法?

1 个答案:

答案 0 :(得分:1)

首先,您需要知道文件块的发送方式,以便了解如何处理它们,例如无论他们使用的是标准HTTP multipart/formdata File Uploads,在这种情况下,它们都将以ServiceStack's Request.Files collection可用,还是以其他方式(如发送原始字节)提供,在这种情况下,您的Request DTO will need to implement IRequiresStream都将访问原始未序列化的字节。

服务器不能保证客户端将如何发送,如果保证客户端仅按顺序发送数据块,则服务器可以假定这是始终发送的方式,但是对于所有服务器,服务器都知道可以并行发送数据块,它可能需要支持的无序并行操作。

我个人会避免通过独立的HTTP API请求分块上传文件,因为这样做会增加大量的复杂性,但是如果文件的大小可以达到50GB,那么您将需要提出一个定制解决方案。

您将像处理任何分块数据一样处理分块(例如,假设您必须手动将多个服务的响应拼接在一起)。由于文件太大,因此无法选择将它们存储在内存中(例如ConcurrentDictionary)。如果您有权访问云存储服务,则可能要在其中上传临时块,否则需要将它们存储在磁盘上。理想情况下,您的解决方案应利用最终的数据存储解决方案来保存文件。

否则,天真的解决方案是服务器应在客户端上载客户端需要发送的文件以及块索引和需要发送的总块之前,生成一个唯一的密钥(如Guid)。然后,每个服务都将首先将该块直接写入磁盘,首先在临时文件路径(Path.GetTempFileName())上,然后在写入文件后将其移动为/uploads/{unique-id}/{chunk-index}.dat之类的格式。

在每个块上载请求的结尾,您都可以检查/uploads/{unique-id}/目录中是否包含所有块,如果它确实启动了将其缝合并创建单个文件的过程。尽管更健壮的方式是让客户端在完成所有块的上传之后启动文件拼接,但是如果拼接失败,您可以手动调用再次拼接文件的服务,而无需让客户端重新-上传文件。