整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML5大文件上传技术

tml5文件分割上传解决方案

html5提供的文件API中可以轻松的对文件进行分割切片, 然后通过javascript异步处理向服务器传输数据, 突破对大文件上传的限制, 同时异步处理在一定程度上也提高了文件上传的效率。用户体验上也优于前述方案。

index.html

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>大文件上传实例</title>
<script type="text/javascript">
    const BYTES_PER_CHUNK = 1024 * 1024; // 每个文件切片大小定为1MB .
    var slices;
    var totalSlices;
    //发送请求
    function sendRequest() {
        var blob = document.getElementById('file').files[0];
        var start = 0;
        var end;
        var index = 0;
        // 计算文件切片总数
        slices = Math.ceil(blob.size / BYTES_PER_CHUNK);
        totalSlices= slices;
        while(start < blob.size) {
        end = start + BYTES_PER_CHUNK;
        if(end > blob.size) {
            end = blob.size;
        }
        uploadFile(blob, index, start, end);
        start = end;
        index++;
        }
    }
    //上传文件
    function uploadFile(blob, index, start, end) {
        var xhr;
        var fd;
        var chunk;
        xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
        if(xhr.readyState == 4) {
        if(xhr.responseText) {
            alert(xhr.responseText);
        }
        slices--;
        // 如果所有文件切片都成功发送,发送文件合并请求。
        if(slices == 0) {
            mergeFile(blob);
            alert('文件上传完毕');
        }
        }
        };
        chunk =blob.slice(start,end);//切割文件
        //构造form数据
        fd = new FormData();
        fd.append("file", chunk);
        fd.append("name", blob.name);
        fd.append("index", index);
        xhr.open("POST", "upload.php", true);
        //设置二进制文边界件头
        xhr.setRequestHeader("X_Requested_With", location.href.split("/")[3].replace(/[^a-z]+/g, '$'));
        xhr.send(fd);
    }
    function mergeFile(blob) {
        var xhr;
        var fd;
        xhr = new XMLHttpRequest();
        fd = new FormData();
        fd.append("name", blob.name);
        fd.append("index", totalSlices);
        xhr.open("POST", "merge.php", true);
        xhr.setRequestHeader("X_Requested_With", location.href.split("/")[3].replace(/[^a-z]+/g, '$'));
        xhr.send(fd);
    }
</script>
</head>
<body>
<input type="file" id="file"/>
<button onclick="sendRequest()">上传</button>
</body>
</html>

upload.php

<?php
//省略了文件接收判断isset部分
//当前目录下建立一个uploads文件夹
//接收文件名时进行转码,防止中文乱码。
$target = "uploads/" .iconv("utf-8","gbk",$_POST["name"]) . '-' . $_POST['index'];
move_uploaded_file($_FILES['file']['tmp_name'], $target);
// Might execute too quickly.
sleep(1);
?>

merge.php

<?php
//文件合并
$target = "uploads/" .iconv("utf-8","gbk",$_POST["name"]);
$dst = fopen($target, 'wb');
for($i = 0; $i < $_POST['index']; $i++) {
$slice = $target . '-' . $i;
$src = fopen($slice, 'rb');
stream_copy_to_stream($src, $dst);
fclose($src);
unlink($slice);
}
fclose($dst);

关键函数stream_copy_to_stream()

int stream_copy_to_stream ( resource $source , resource $dest [, int $maxlength = -1 [, int $offset = 0 ]] )

<?php
$src = fopen('http://www.example.com', 'r');
$dest1 = fopen('first1k.txt', 'w');
$dest2 = fopen('remainder.txt', 'w');
echo stream_copy_to_stream($src, $dest1, 1024) . " bytes copied to first1k.txt\n";
echo stream_copy_to_stream($src, $dest2) . " bytes copied to remainder.txt\n";
?>
var blob = document.getElementById('file').files[0];
console.dir(blob);

相关的属性如下:

lastModified: 1511081596000

lastModifiedDate: Sun Nov 19 2017 16:53:16 GMT+0800 (中国标准时间) {}

name: "IMG_20171119_165316.jpg"

size: 4383101

type: "image/jpeg"

slice: ƒ slice() 用于切割文件

后台看到访问记录,很多用户提了这个需求,要求用HTML5来实现。网上搜了一下,发现这类需求很多,相关的文章和代码也很多,大部分用的是VUE,H5的也有,不过只提供了前端部分,后端的没有。然后也不完善,花了很多的时间找了一些,有的用是能用,但是小问题太多,找这些能用的代码,所花的时间都能够完全自已写一个出来了。很多代码后续维护也是个问题,找不到原技术人员,也没有完善的文档,开发维护都靠自已,这样花的时间有点不值得。


代码:https://gitee.com/xproer/up6-vue-cli

1.引入up6组件

2.配置接口地址

接口地址分别对应:文件初始化,文件数据上传,文件进度,文件上传完毕,文件删除,文件夹初始化,文件夹删除,文件列表

参考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de

3.定义事件

TML5实现大文件上传下载,HTML5实现大文件上传下载解决方案,HTML5实现大文件上传下载思路,HTML5实现大文件上传下载源码,HTML5实现大文件上传下载实例,HTML5实现大文件分块上传下载,HTML5实现大文件分片上传下载,HTML5实现大文件切片上传下载,HTML5实现大文件加密上传下载,HTML5实现文件夹上传下载,


用户上传的文件比较大,有20G左右,直接用HTML传的话容易失败,服务器也容易出错,需要分片,分块,分割上传。也就是将一个大的文件分成若干个小文件块来上传,另外就是需要实现秒传功能和防重复功能,秒传就是用户如果上传过这个文件,那么直接在数据库中查找记录就行了,不用再上传一次,节省时间,实现的思路是对文件做MD5计算,将MD5值保存到数据库,算法可以用MD5,或者CRC,或者SHA1,这个随便哪个算法都行。

分片还需要支持断点续传,现在HTML5虽然提供了信息记录功能,但是只支持到了会话级,也就是用户不能关闭浏览器,也不能清空缓存。但是有的政府单位上传大文件,传了一半下班了,明天继续传,电脑一关结果进度信息就丢失了,这个是他们的一个痛点。

切片的话还有一点就是在服务器上合并,一个文件的所有分片数据上传完后需要在服务器端进行合并操作。

支持文件下载,批量下载,下载断点续传,加密下载,端到端加密,加密算法支持国密SM4,多线程下载

支持在服务端保存文件夹层级结构,支持将文件夹层级结构信息保存到数据库中,支持下载时能够将文件夹层级结构下载下来,支持下载文件夹,下载文件夹支持断点续传,

支持加密传输,包括加密上传,加密下载,加密算法支持国密SM4,

对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传

从上传的效率来看,利用多线程并发上传能够达到最大效率。


1.下载示例

https://gitee.com/xproer/up6-vue-cli



将up6组件复制到项目中

示例中已经包含此目录



1.引入up6组件



2.配置接口地址

接口地址分别对应:文件初始化,文件数据上传,文件进度,文件上传完毕,文件删除,文件夹初始化,文件夹删除,文件列表

参考:http://www.ncmem.com/doc/view.aspx?id=e1f49f3e1d4742e19135e00bd41fa3de



3.处理事件



启动测试



启动成功



效果



数据库



源码工程文档:https://drive.weixin.qq.com/s?k=ACoAYgezAAw1dWofra

源码报价单:https://drive.weixin.qq.com/s?k=ACoAYgezAAwoiul8gl


OEM版报价单:https://drive.weixin.qq.com/s?k=ACoAYgezAAwuzp4W0a

产品源代码:https://drive.weixin.qq.com/s?k=ACoAYgezAAwbdKCskc
授权码生成器:https://drive.weixin.qq.com/s?k=ACoAYgezAAwTIcFph1