文件上传之秒传文件

栏目: IT技术 · 发布时间: 3年前

内容简介:我们在使用云盘上传文件时会发现秒传文件,速度极快,这是怎么回事呢?秒传文件其实是因为我们要上传的文件前,服务端已经查询到该文件已经存在,没必须再传一份一模一样的文件,直接告诉前端文件已经传好了,让用户有了飞快的感觉。

我们在使用云盘上传文件时会发现秒传文件,速度极快,这是怎么回事呢?秒传文件其实是因为我们要上传的文件前,服务端已经查询到该文件已经存在,没必须再传一份一模一样的文件,直接告诉前端文件已经传好了,让用户有了飞快的感觉。

为了阅读和开发方便,我将文件上传系列相关文章章节列出来,建议从01节开始看起,文章内容按顺序紧紧相连:

本系列文章相关源码已经上传到github上,请参照下载: https://github.com/lrfbeyond/fast-uploader

为什么会秒传

前面说了,因为服务端已经知道文件已经存在服务器端了,也就是说我们要传的这个文件,此前已经至少上传过一次了。这个文件有可能是我们自己上传的,也有可能是别人上传的。

这正是用户需要的,秒传文件,节省上传时间。对后端服务器来说,节约存储空间,同样的文件没必要存成多个文件,同时也节约带宽,当然是好事了。

那服务端是如何知道文件已经上传过了呢?

答案就是MD5。在上一节中我们知道上传前要检测文件md5值。那么本节文章我们将给您介绍如何在文件上传时将md5告诉后端,后端程序如何判断文件已经上传的?

秒传流程

file.uniqueIdentifier

准备

1.本文前端基于vue-simple-uploader上传组件,如果您还不了解该组件,请先查看本系列文章01节相关内容。

2.本文后端使用php+mysql,您需要具备相关知识。

3.在 mysql 数据库中建立hw_file表,表结构如下:

DROP TABLE IF EXISTS `hw_file`;
CREATE TABLE `hw_file` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `filename` varchar(255) NOT NULL COMMENT '文件名',
  `filesize` int(11) NOT NULL DEFAULT '0' COMMENT '文件大小',
  `md5` varchar(32) NOT NULL COMMENT '文件md5',
  `type` varchar(10) NOT NULL COMMENT '文件类型',
  `filepath` varchar(128) NOT NULL COMMENT '文件保存路径',
  `created_at` datetime NOT NULL COMMENT '上传时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4;

前端发送秒传验证请求

首先,确保开启了服务端分片校验功能,这个功能在vue-simple-uploader的options选项中设置, testChunks: true , 默认是true开启状态的。

接着选中文件,准备上传前需要计算该文件的md5,关于md5的计算请查看上一节文章。

开启了分片校验功能,目的是每次在正式上传前先向后端发送个get请求,用来实现秒传、续传功能的。

文件上传之秒传文件

在这个get请求中,在url中会携带文件的md5等相关信息一起传给后端。

在后端验证好文件md5后,会返回相应的是否秒传的标识 isExist ,前端要识别这个标识,并及时更新文件上传状态。

在options选项中添加函数 checkChunkUploadedByResponse() ,该函数响应后台返回message信息,同时检测分片信息是否上传完整,在后面的断点续传章节会讲到验证分片。

// 服务器分片校验函数
checkChunkUploadedByResponse: (chunk, message) => {
    let obj = JSON.parse(message);
    if (obj.isExist) {
        this.statusTextMap.success = '秒传文件';
        return true;
    }
},

很显然,当检测到 obj.isExist 是true的时候,则表明文件已经存在了,这是直接将文件的上传状态改成:“秒传文件”,并结束上传。

后端验证MD5实现秒传

我们还是继续上一节的后端php文件:Uploader.php。

在获取到前端请求过来的参数中,文件唯一标志 identifier 就是该文件的md5值。然后根据该文件的md5值和该文件的大小filesize,这两个参数,查询hw_file表,得到满足md5和filesize都相当的记录,如果存在记录,则该文件已经上传过了。返回秒传标识: isExist = true 以及文件路径。如果文件不存在,那么就开始上传文件。

//检测断点和md5
public function checkFile()
{
    $identifier = $this->fileInfo['identifier'];

    //检测文件md5是否已经存在
    $rs = $this->checkMd5($identifier, $this->fileInfo['totalSize']);
    return $rs;
}

//检测md5表是否已存在该文件
private function checkMd5($md5, $filesize)
{
    $db = self::mysql();
    $sql = "SELECT count(*) as t,filepath FROM `hw_file` WHERE md5=:md5 AND filesize=:filesize";
    $stmt = $db->prepare($sql);
    $stmt->execute([
        ':md5' => $md5,
        ':filesize' => $filesize
    ]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    $count = $row['t'];
    if ($count > 0) {
        $res['isExist'] = true;
        $res['filepath'] = $row['filepath'];
    } else {
        $res['isExist'] = false;
    }
    return $res;
}

运行后,从前端选中文件上传,第一次上传成功:

文件上传之秒传文件

第二次选择同一个文件上传,或者将文件改名再上传,或者换个浏览器换个终端上传同一个文件,都会是秒传的效果:

文件上传之秒传文件

好了,关于秒传我们就先讲到这里,前后端的具体代码已经上传到github上了,请直接下载运行。

接下来一篇文章,我会介绍如何实现断点续传,跨终端续传文件,敬请关注。


以上所述就是小编给大家介绍的《文件上传之秒传文件》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Effective Ruby:改善Ruby程序的48条建议

Effective Ruby:改善Ruby程序的48条建议

Peter J. Jones / 杨政权、秦五一、孟樊超 / 机械工业出版社 / 2016-1 / 49

如果你是经验丰富的Rub程序员,本书能帮助你发挥Ruby的全部力量来编写更稳健、高效、可维护和易执行的代码。Peter J.Jones凭借其近十年的Ruby开发经验,总结出48条Ruby的最佳实践、专家建议和捷径,并辅以可执行的代码实例。 Jones在Ruby开发的每个主要领域都给出了实用的建议,从模块、内存到元编程。他对鲜为人知的Ruby方言、怪癖、误区和强力影响代码行为与性能的复杂性的揭......一起来看看 《Effective Ruby:改善Ruby程序的48条建议》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具