html5大文件上传技术

html5大文件上传技术
引言

普通html表单在上传几KB或几MB级别的文件基本无压力,但在上传上百MB甚至是GB级别大文件很无爱。而且一般服务器单个文件上传限制基本都在几MB之内。如何有效突破限制,上传大文件技术值得深入探讨。

html5大文件上传技术
一般解决方案
html5文件分割上传解决方案
代码实现
运行截图
上传文件相关问题讨论
安全问题
用户体验优化
上传性能优化
一般解决方案
html5文件分割上传
上传相关问题讨论
一般解决方案
一般解决方案粗劣总结主要由以下几种:

FTP

使用ftp一般能满足上传大文件需求,但是从用户角度来讲,ftp方式大众普及度不高,用户使用还得学习。 
理想的状态下是没必要让用户知道的就不需要让用户知道,无知是福,简单是美。不要去轻易挑战用户积累的使用习惯,让用户感觉不到上传大文件和小文件的差异。

相关组件插件开发

一些诸如网盘、邮箱之类的在上传大文件时会开发一些相关插件来解决问题,但从用户角度讲,网页顶部会弹出一些安装插件的提示,容易产生厌烦、抵触、怀疑等不良使用情绪,效果还是有些折扣。

修改服务器配置

也有一些修改服务器最大上传配置的做法,诸如修改php.ini、IIS之类,这种做法在用户界面层面是感觉不到差异了,但是这种做法相对粗糙,对资源利用的效率不高,大文件传输卡顿超时、浏览器崩溃等问题非常明显,使用体验还是很糟糕。

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

代码实现
下面以php为例,讲一下具体实现过程。在html端将文件进行切割,提交给upload.php1,upload.php将上传的文件片移到文件夹临时存放.当最后一块文件片成功提交到upload.php后,向merge.php提交一个合并文件片的请求。2

核心代码如下: 
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>

猜你喜欢

转载自blog.csdn.net/aryasei/article/details/87161408