文件秒传、分块上传、断点续传的原理

用 md5 识别文件

根据 md5 来唯一识别一个文件。如果两个文件的 md5 相同,则认为它们是同一个文件。

区分 entity 表和 record 表
  • entity 表:文件实体表,存储文件实体的信息:文件的 md5、文件的大小、文件的存储路径等。
  • record 表:文件记录表,存储业务信息:文件的上传者、上传时间、对应的文件实体的 entityId等。

如果五个用户上传了同一个 PPT 文件。entity 表中只会有一条记录;record 表中会有5条记录,这5条记录的 entityId 是相同的。

秒传的原理

上传文件之前,浏览器先计算出文件的 md5 值并发送给服务器(只发送 md5 ,不发送文件实体)。

服务器收到 md5 值之后,在 entity 表中查询是否有相同的文件。如果查到了,那么这次“上传”就不需要真的去传输文件了,可以直接向 record 表中添加记录,也就实现了秒传

分块上传的原理

上传文件之前,浏览器把文件切成一块一块的,然后分别发送给服务器。在发送每一小块时,除了传输当前块的内容,还需要携带如下信息:

  • 文件的 md5 值
  • 文件大小
  • 文件切成多少块
  • 当前块是第几块

服务器也是一块一块进行接收。有三个关键点:

  • entity 表中有一条当前实体文件的数据。这条数据的上传状态 status 的值初始化为0,当所有块都收到后才把status的值改为1,标志着文件上传完成。
  • .temp 文件:是“拼凑中”的文件,初始化为空。服务器收到每个块时,就把块的内容写进 .temp 文件相应的位置。
  • .progress 文件:记录进度的文件。
    • 初始化进度:根据文件总块数进行初始化。如果文件共分成2块,则初始化为"00"。如果文件共分成4块,则初始化为“0000”。
    • 记录进度:服务器收到每个块时,就把 .progress 文件中块对应位置的0改为1。

断点续传的原理

服务器在收到每一块的时候,都需要拿着 md5 值去 entity 表中查询。

如果在 entity 表中查到了记录并且 status 为0,说明这个文件传过但是没有传完。服务器去对应的 .progress 文件中查询并把进度返回给浏览器。

这样,浏览器只会传输没传过的块了,也就实现了断点续传

上传流程

上传前校验
计算md5
上传
上传后校验
成功
  1. 上传前校验
    校验剩余空间是否足够(传参fileSize),校验文件路径和文件名中是否包含敏感词(传参filePath)
    校验成功,则开始计算md5;校验失败,则流程结束。

  2. 计算md5
    使用分块、排队、多线程这三个策略缓解计算压力,具体看 计算文件 MD5
    计算 md5 完成之后,开始上传文件。

  3. 上传
    先发送一个 GET 查询请求,询问该文件是否秒传或者断点续传

    • 如果是秒传,页面不发送任何一个块的 POST 请求,直接显示文件的上传进度100%。直接开始上传后校验。
    • 如果是断点续传,服务器告诉浏览器还缺少哪些块。浏览器把剩下的块用 POST 请求一个一个发给后台。
    • 如果都不是,则把文件的所有块用 POST 请求一个一个发给后台。

    服务器收到所有的块之后,上传完成,开始上传后校验。

  4. 上传后校验
    对文件内容进行敏感词校验。
    如果校验成功,服务器向 record 表中新加一条数据,浏览器页面中显示文件上传成功。

猜你喜欢

转载自blog.csdn.net/tangran0526/article/details/100030623