Home  >  Article  >  Web Front-end  >  Tutorial example of h5 uploading large files in web pages

Tutorial example of h5 uploading large files in web pages

零下一度
零下一度Original
2017-05-11 14:24:362702browse

UtilizeHTML5ShardingUploadVery large files

Directly uploading large files to web pages has always been a headache. The main problems generally include two types : First, if an error occurs during the upload time, all efforts will be wasted; second, the server configuration is complex, and the issue of receiving oversized forms and timeouts must be considered. If it is a managed host, the configuration may not be changed, and by default it can only receive attachments smaller than 4MB.

The ideal solution is to fragment the large file and send it to the server one by one, and then merge it by the server. The advantage of this is that once the upload fails, only one fragment is lost, and the entire file does not need to be retransmitted. Moreover, the size of each fragment can be controlled within 4MB, and the server can adapt without making any settings.

The commonly used solution is RIA. Taking flex as an example, the FileReference.load method is usually used to load the file to obtain a ByteArray, and then construct the form in slices (higher versions of flash do not allow direct access to the file). However, this load method can only load smaller files, approximately no more than 300MB, so its applicability is not very strong.

Fortunately, now that we have HTML5, we can directly construct shards. This is a very gratifying progress, but it is a pity that it is not widely applicable at present (IE, IE, I really hate you so much).

Let’s get back to the point, let’s take a look at a DEMO, based on ASP.Net MVC3, it’s just an example, and many issues have been simplified.

Mainly on the client side, new features are reflected here:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>HTML5大文件分片上传示例</title>
    <script src="../Scripts/jquery-1.11.1.min.js"></script>
    <script>
    var page = {
        init: function(){
            $("#upload").click($.proxy(this.upload, this));
        },
       
        upload: function(){
            var file = $("#file")[0].files[0],  //文件对象
                name = file.name,        //文件名
                size = file.size,        //总大小
                succeed = 0;
                 
            var shardSize = 2 * 1024 * 1024,    //以2MB为一个分片
                shardCount = Math.ceil(size / shardSize);  //总片数
                 
            for(var i = 0;i < shardCount;++i){
                //计算每一片的起始与结束位置
                var start = i * shardSize,
                    end = Math.min(size, start + shardSize);
                //构造一个表单,FormData是HTML5新增的
                var form = new FormData();
                form.append("data", file.slice(start,end));  //slice方法用于切出文件的一部分
                form.append("name", name);
                form.append("total", shardCount);  //总片数
                form.append("index", i + 1);        //当前是第几片
               
                //Ajax提交
                $.ajax({
                    url: "../File/Upload",
                    type: "POST",
                    data: form,
                    async: true,        //异步
                    processData: false,  //很重要,告诉jquery不要对form进行处理
                    contentType: false,  //很重要,指定为false才能形成正确的Content-Type
                    success: function(){
                        ++succeed;
                        $("#output").text(succeed + " / " + shardCount);
                    }
                });
            }
        }
    };
    $(function(){
        page.init();
    });
    </script>
</head>
<body>
    <input type="file" id="file" />
    <button id="upload">上传</button>
    <span id="output" style="font-size:12px">等待</span>
</body>
</html>

The slice method and FormData here did not exist before html5. Through this method, our form is constructed like this. Take a look at the packet capture:

Tutorial example of h5 uploading large files in web pages

You can see that the constructed Content-Type is multipart/form-data. That is, the most traditional file upload form that complies with RFC standards. In addition, the attributes such as name and total that we transmit at the same time are also in the form.

Then there is the server, there is nothing new, it is just receiving an ordinary file:

[HttpPost]
public ActionResult Upload()
{
    //从Request中取参数,注意上传的文件在Requst.Files中
    string name = Request["name"];
    int total = Convert.ToInt32(Request["total"]);
    int index = Convert.ToInt32(Request["index"]);
    var data = Request.Files["data"];
   
    //保存一个分片到磁盘上
    string dir = Server.MapPath("~/Upload");
    string file = Path.Combine(dir, name + "_" + index);
    data.SaveAs(file);
   
    //如果已经是最后一个分片,组合
    //当然你也可以用其它方法比如接收每个分片时直接写到最终文件的相应位置上,但要控制好并发防止文件锁冲突
    if(index == total)
    {
        file = Path.Combine(dir, name);
        var fs = new FileStream(file, FileMode.Create);
        for(int i = 1;i <= total;++i)
        {
            string part = Path.Combine(dir, name + "_" + i);
            var bytes = System.IO.File.ReadAllBytes(part);
            fs.Write(bytes, 0, bytes.Length);
            bytes = null;
            System.IO.File.Delete(part);
        }
        fs.Close();
    }
   
    //返回是否成功,此处做了简化处理
    return Json(new { Error = 0 });
}

Many problems in the above DEMO are simplified, such as nothing doneException handling , the client does not judge whether the server has made an error and retry, you can improve it yourself.

Based on the above, we can make many functional extensions. For example, we can control whether all shards are uploaded sequentially or concurrently to suit different applications. For another example, we can calculate the corresponding HASH before uploading the whole file and before uploading in parts, and send a request to ask the server whether the file already exists. If it exists, do not upload it again. This is achieved. "Extremely fast upload" and "Breakpoint resume upload"

[Related recommendations]

1. Free h5 online video tutorial

2 . HTML5 Complete Manual

3. php.cn Original HTML5 Video Tutorial

The above is the detailed content of Tutorial example of h5 uploading large files in web pages. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn