如何解决网站大文件上传问题?


「系统设计面试题」如何解决网站大文件上传问题?

如果你的项目涉及到文件上传的话,面试官很可能会问你这个问题。

我们先看第一个场景:大文件上传中途,突然失败!

试想一个,你想上传一个 5g 的视频,上传进度到 99% 的时候,特么的,突然网络断了,这个时候,你发现自己竟然需要重新上传。我就问你抓狂不?

有没有解决办法呢? 答案就是:分片上传!

什么是分片上传呢? 简单来说,我们只需要先将文件切分成多个文件分片(就像我下面绘制的图片所展示的那样),然后再上传这些小的文件分片。

前端发送了所有文件分片之后,服务端再将这些文件分片进行合并即可。

使用分片上传主要有下面 2 点好处:

  1. 断点续传 :上传文件中途暂停或失败(比如遇到网络问题)之后,不需要重新上传,只需要上传哪些未成功上传的文件分片即可。所以,分片上传是断点续传的基础。
  2. 多线程上传 :我们可以通过多线程同时对一个文件的多个文件分片进行上传,这样的话就大大加快的文件上传的速度。

前端怎么生成文件分片呢?后端如何合并文件分片呢?

前端可以通过 Blob.slice() 方法来对文件进行切割(File 对象是继承 Blob 对象的,因此 File 对象也有 slice() 方法)。

生成文件切片的示例代码如下:

RandomAccessFile 类可以帮助我们合并文件分片,示例代码如下:

何为秒传?

秒传说的就是我们在上传某个文件的时候,首先根据文件的唯一标识判断一下服务端是否已经上传过该文件,如果上传过的话,直接就返回给用户文件上传成功即可。

一般情况下,这个唯一标识都是通过对文件的名称、最后修改时间等信息取 MD5 值得到的,这个可以通过使用 spark-md5 这个库来生成。

需要注意的是:你不能根据文件名就决定文件是否已经上传到服务端,因为很可能存在文件名相同,但是,内容不同的情况。另外,体验更好的是文件内容不变,唯一标识就不应该改变。因此,我们可以根据文件的内容来计算 MD5 值。

另外,还存在一种情况是我们要上传的文件已经上传了部分文件切片到服务端。这个时候,我们直接返回已上传的切片列表给前端即可。

然后,前端再将剩余未上传的分片上传到服务端。

我简单画了一张图描述一下断点续传和秒传。




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score