2

html5文件上传

概念

分片

推荐的分块大小是2M-5M,具体size根据产品中文件上传的大小分布来定。如果上传的文件大部分是500M以上,很大的文件,建议是5M, 如果相对较小,推荐2M。

断点续传

好处
  1. 节省流量,避免上传重复的分块。

  2. 减少用户等待时间。

  3. 可恢复的上传。出现中断,就算浏览器刷新或者是换了台电脑也能恢复到上次中断的位置。

核心代码

以下代码上传音频有点问题,上传进度没有做,日后闲时补上。

javascript

(function ($, global, doc) {
    var form = doc.forms["upload"];

    // Upload类
    function Upload (file) {
        this.file = file;
        this.fileInfo = {
            fileName: this.file.name,
            fileType: this.file.type,
            fileSize: this.file.size
        };

        this.reader = new FileReader();
        // 开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据.
        this.reader.readAsBinaryString(this.file);

        // 块大小默认为4MB
        this.opts = {
            chunkSize: 4 * 1024 * 1024,
            chunkIndex: 0
        };
        $.extend(this.opts, {
            chunkCount: Math.ceil(this.fileInfo.fileSize / this.opts.chunkSize)
        });

        this.bindEvent();

        return this;
    };
    Upload.prototype = {
        bindEvent: function () {
            var self = this;

            self.reader.onloadstart = function () {
                self.uploadChunk();
            };

            return self;
        },
        uploadFinish: function (data) {
            var self = this;
            var previewStr = '';

            switch (self.fileInfo.fileType.substring(0, self.fileInfo.fileType.indexOf('/'))) {
                case 'image':
                                previewStr = '<img src="' + ('upload/' + data.url) + '">';
                                $('.preview').html(previewStr);
                                break;
                case 'audio':
                                previewStr = '<audio src="' + ('upload/' + data.url) + '" controls="controls"></audio>';
                                break;

                default:
                                $('.preview').html(previewStr);
            }

            return self;
        },
        updateProcess: function () {


            return this;
        },
        uploadChunkAfter: function (data) {
            var self = this;

            self.opts.chunkIndex++;
            if (self.opts.chunkIndex < self.opts.chunkCount) {
                self.uploadChunk();
            } else {
                self.uploadFinish(data);
            }

            updateProcess();

            return self;
        },
        uploadChunk: function () {
            var fData = new FormData();
            var self = this;

            fData.append("file", self.file.slice(self.opts.chunkIndex * self.opts.chunkSize, self.opts.chunkSize * (self.opts.chunkIndex + 1)));
            fData.append("fileName", self.fileInfo.fileName);
            fData.append("fileSize", self.fileInfo.fileSize);
            fData.append("fileType", self.fileInfo.fileType);
            fData.append("chunkCount", self.opts.chunkCount);
            fData.append("chunkIndex", self.opts.chunkIndex);
            fData.append("trueName", self.fileInfo.fileName.substring(0, self.fileInfo.fileName.lastIndexOf('.')));
            $.ajax({
                url: 'controller/upload.php',
                type: 'POST',
                data: fData,
                processData: false,
                contentType: false,
                cache: false,
                dataType: "json",
                success: function (data) {
                    self.uploadChunkAfter(data);
                }
            });

            return self;
        },
        util: function () {
            return {
                // 字节转换成对应的单位
                bytesTosize: function (data) {
                    var unit = ["Bytes", "KB", "MB", "GB"];
                    var i = parseInt(Math.log(data) / Math.log(1024));
                    return (data / Math.pow(1024, i)).toFixed(1) + " " + unit[i];
                },
                // 秒转换成对应的时间
                secondsTotime: function (sec) {
                    var h = Math.floor(sec / 3600),
                        m = Math.floor((sec - h * 3600) / 60),
                        s = Math.floor(sec - h * 3600 - m * 60);
                    if(h < 10) h = "0" + h;
                    if(m < 10) m = "0" + m;
                    if(s < 10) s = "0" + s;

                    return h + ":" + m + ":" + s;
                }
            }
        }
    };

    $('#submit').on('click', function () {
        var File = new Upload(form["file"].files[0]);

        return false;
    });
})(jQuery, window, document);

html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>分块上传</title>
</head>
<body>
    <form name="upload" action="" enctype="multipart/form-data" method="post">
        <input type="file" id="file" name="file">
        <input type="button" id="submit" value="提交">
    </form>
    <div class="preview"></div>
    <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
    <script src="js/upload.js"></script>
</body>
</html>

php

<?php
    $fsize = $_POST['fileSize'];
    $findex =$_POST['chunkIndex'];
    $ftotal =$_POST['chunkCount'];
    $ftype = $_POST['fileType'];
    $fdata = $_FILES['file'];
    $fname = mb_convert_encoding($_POST['fileName'],"gbk","utf-8");
    $truename = mb_convert_encoding($_POST['trueName'],"gbk","utf-8");

    $path = "../";
    $dir = $path."upload/".$truename."-".$fsize;
    $save = $dir."/".$fname;
    if(!is_dir($dir))
    {
        mkdir($dir);
        chmod($dir,0777);
    }

    //读取临时文件内容
    $temp = fopen($fdata["tmp_name"],"r+");
    $filedata = fread($temp,filesize($fdata["tmp_name"]));

    //将分段内容存放到新建的临时文件里面
    if(file_exists($dir."/".$findex.".tmp")) unlink($dir."/".$findex.".tmp");
    $tempFile = fopen($dir."/".$findex.".tmp","w+");
    fwrite($tempFile,$filedata);
    fclose($tempFile);

    fclose($temp);

    if($findex+1 == $ftotal)
    {
        if(file_exists($save)) @unlink($save);
        //循环读取临时文件并将其合并置入新文件里面
        for($i=0;$i<$ftotal;$i++)
        {
            $readData = fopen($dir."/".$i.".tmp","r+");
            $writeData = fread($readData,filesize($dir."/".$i.".tmp"));

            $newFile = fopen($save,"a+");
            fwrite($newFile,$writeData);
            fclose($newFile);

            fclose($readData);

            $resu = @unlink($dir."/".$i.".tmp");
        }
        $res = array("res"=>"success","url"=>mb_convert_encoding($truename."-".$fsize."/".$fname,'utf-8','gbk'));
        echo json_encode($res);
    }
?>

参考文档

fex


luckyyulin
217 声望9 粉丝

有一种鸟没有脚,他的一生只能在天上飞来飞去,飞累了就在风里睡觉,一辈子只能落地一次,那就是他死的时候