사용 웹 페이지에 대용량 파일을 직접 업로드하는 것은 일반적으로 두 가지 유형의 골칫거리였습니다. 첫째, 업로드하는 동안 오류가 발생하면 모든 노력이 낭비됩니다. 둘째, 서버 구성이 복잡하고, 크기가 큰 양식을 수신하는 문제와 시간 초과 문제를 고려해야 합니다. 관리되는 호스트인 경우 구성이 불가능할 수 있습니다. 변경되었으며 기본적으로 4MB보다 작은 첨부파일만 수신할 수 있습니다.
이상적인 솔루션은 대용량 파일을 조각화하여 하나씩 서버로 보낸 다음 서버에서 병합하는 것입니다. 이 방법의 장점은 업로드에 실패하면 하나의 조각만 손실되고 전체 파일을 다시 전송할 필요가 없다는 것입니다. 또한 각 조각의 크기를 4MB 이내로 제어할 수 있으며 서버는 별도의 설정 없이도 적응할 수 있습니다. .
일반적으로 사용되는 솔루션은 RIA입니다. flex를 예로 들면 FileReference.load 메서드는 일반적으로 파일을 로드하여 ByteArray를 얻은 다음 양식을 슬라이스로 구성하는 데 사용됩니다(플래시 상위 버전에서는 그렇지 않음). 파일에 대한 직접 액세스를 허용합니다). 그러나 이 로드 방법은 약 300MB 이하의 작은 파일만 로드할 수 있으므로 적용성이 그다지 강력하지 않습니다.
다행히 이제 HTML5가 있어서 직접 샤드를 구성할 수 있게 되었는데, 이는 매우 만족스러운 진전이지만 현재는 널리 적용되지 않는 점이 아쉽습니다(IE, IE, 정말 싫습니다. 많이).
본점으로 돌아가 ASP.Net MVC3를 기반으로 한 DEMO를 살펴보겠습니다. 이는 단지 예시일 뿐이며 많은 문제가 단순화되었습니다.
주로 클라이언트 측의 새로운 기능이 여기에 반영됩니다.
<%@ 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>
여기의 슬라이스 메소드와 FormData는 html5 이전에는 존재하지 않았습니다. 이 방법을 통해 우리의 양식은 다음과 같이 구성됩니다. 패킷 캡처를 살펴보세요.
구성된 Content-Type이 multipart/form-data임을 알 수 있습니다. 즉, RFC 표준을 준수하는 가장 전통적인 파일 업로드 형식입니다. 또한 동시에 전송하는 이름, 합계 및 기타 속성도 형식으로 되어 있습니다.
그런 다음 서버가 있고 새로운 것은 없으며 단지 일반 파일을 받는 것뿐입니다.
[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 }); }
위 DEMO의 많은 문제는 아무것도 수행되지 않는 등 단순화되었습니다.예외 처리 클라이언트는 서버에 오류가 발생했는지 판단하고 재시도하는 것이 아니라 사용자가 직접 개선할 수 있습니다.
위를 기반으로 다양한 기능 확장을 만들 수 있습니다. 예를 들어, 다양한 애플리케이션에 맞게 모든 샤드를 순차적으로 업로드할지 아니면 동시에 업로드할지 제어할 수 있습니다. 또 다른 예로, 전체 파일을 업로드하기 전과 부분적으로 업로드하기 전에 해당 HASH를 계산하고, 파일이 이미 존재하는지 서버에 물어보는 요청을 보낼 수 있습니다. . "매우 빠른 업로드" 및 "재개 가능한 업로드"
[관련 권장 사항]
2 . HTML5 정식 버전 매뉴얼
위 내용은 웹 페이지에 대용량 파일을 업로드하는 h5의 튜토리얼 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!