在編寫前端的過程中,難免會遇到檔案上傳的問題,當使用者要上傳較大的檔案是,會被伺服器端限制,阻止其上傳,在ASP.Net中,調整伺服器接受檔案的大小的設定方法如下:
在ASP中設定Web.config檔的httpRuntime:
<httpRuntime executionTimeout="90" maxRequestLength="40960" useFullyQualifiedRedirectUrl="false"minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100" enableVersionHeader="false"/>
其中各參數的功能為:
executionTimeout :表示允許執行請求的最大時間限制,單位為秒 。
maxRequestLength:指示 ASP.NET支援的最大檔案上載大小。此限制可用於防止因使用者將大量檔案傳遞到該伺服器而導致的拒絕服務攻擊。指定的大小以 KB 為單位。預設值為 4096KB (4 MB)。
useFullyQualifiedRedirectUr:表示指示客戶端重定向是否是完全限定的(採用”http://server/path” 格式,這是某些移動控件所必需的),或者指示是否代之以將相對重定向發送到客戶端。如果為True,則所有不是完全限定的重定向都會自動轉換為完全限定的格式。 false 是預設選項。
minFreeThreads:表示指定允許執行新要求的自由執行緒的最小數目。 ASP.NET為要求附加執行緒來完成其處理的請求而使指定數目的執行緒保持自由狀態。預設值為 8。
minLocalRequestFreeThreads:表示ASP.NET保持的允許執行新本機請求的自由執行緒的最小數目。此執行緒數目是為從本機傳入的請求而保留的,以防某些請求在其處理期間發出對本機的子請求。這避免了可能的因遞歸重新進入Web 伺服器而導致的死鎖。
appRequestQueueLimit:表示ASP.NET將為應用程式排隊的請求的最大數目。當沒有足夠的自由線程來處理請求時,將對請求進行排隊。當佇列超出了該設定中指定的限制時,將透過「503 -伺服器太忙」錯誤訊息拒絕傳入的請求。 enableVersionHeader:表示指定 ASP.NET是否要輸出版本標頭。 Microsoft Visual Studio 2005 使用此屬性來決定目前使用的 ASP.NET版本。對於生產環境,該屬性不是必需的,可以停用。
但是,即使把伺服器的設定中的上傳檔案大小寫的夠大,又會受到IIS的限制,而且也無法提供使用者安全的服務。那有沒有一種方法能解決大檔案上傳的問題呢?
肯定是有的:分片上傳。
分片上傳是指將想要上傳的檔案在前端切割成大小很小的小塊,然後再傳給伺服器,從伺服器端再將檔案組合成整的檔案。
先從前端說起,在分片上傳的過程中,前端任務是將檔案分片,分片的辦法有很多,例如可以使用WebUpLoader提供的上傳元件進行分片,也可以用JS與JQ提供的程式碼進行上傳,程式碼實例如下:
var BYTES_PER_CHUNK = 1024 * 1024; // 每个文件切片大小定为1MB . var slices; var totalSlices; //发送请求 function sendRequest() { var blob = document.getElementById("yourID").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++; if ( index>=totalSlices ) alert("Complete!!"); } } //上传文件 function uploadFile(blob, index, start, end) { var xhr; var fd; var chunk; var sliceIndex=blob.name+index; chunk =blob.slice(start,end);//切割文件 fd = new FormData(); fd.append("FileName", chunk, sliceIndex); var xhr = new XMLHttpRequest(); xhr.open('POST', 'Server URL', false);//false,同步上传;ture,异步上传 xhr.send(fd); if((xhr.status >=200 && xhr.status < 300) || xhr.status == 304){ setTimeout("",10); }else{ uploadFile(blob, index, start, end); } }
有了前端,當然少不了在後端的接受與組合,在這裡我用ASP.Net為例,說明如何接收與組合檔案。
public void RecoveryKPJD() { HttpContext context = System.Web.HttpContext.Current; context.Response.ContentType = "text/plain"; //如果进行了分片 if (context.Request.Form.AllKeys.Any(m => m == "chunk")) { //取得chunk和chunks int chunk = Convert.ToInt32(context.Request.Form["chunk"]);//当前分片在上传分片中的顺序(从0开始) int chunks = Convert.ToInt32(context.Request.Form["chunks"]);//总分片数 //根据GUID创建用该GUID命名的临时文件夹 string folder = Your Path + context.Request["guid"] + "/"; string path = folder + chunk; //建立临时传输文件夹 if (!Directory.Exists(Path.GetDirectoryName(folder))) { Directory.CreateDirectory(folder); } FileStream addFile = new FileStream(path, FileMode.Append, FileAccess.Write); BinaryWriter AddWriter = new BinaryWriter(addFile); //获得上传的分片数据流 HttpPostedFile file = context.Request.Files[0]; Stream stream = file.InputStream; BinaryReader TempReader = new BinaryReader(stream); //将上传的分片追加到临时文件末尾 AddWriter.Write(TempReader.ReadBytes((int)stream.Length)); //关闭BinaryReader文件阅读器 TempReader.Close(); stream.Close(); AddWriter.Close(); addFile.Close(); TempReader.Dispose(); stream.Dispose(); AddWriter.Dispose(); addFile.Dispose(); if (chunk == chunks - 1) { //合并文件 ProcessRequest(context.Request["guid"], Path.GetExtension(file.FileName)); } } else//没有分片直接保存 { string targetPath = ""; //此处写文件的保存路径 context.Request.Files[0].SaveAs(targetPath); } } private void ProcessRequest(string guid, string fileExt) { HttpContext context = System.Web.HttpContext.Current; context.Response.ContentType = "text/plain"; string sourcePath = Path.Combine("Your Path", guid + "/");//源数据文件夹 string targetPath = Path.Combine("Your Path", Guid.NewGuid() + fileExt);//合并后的文件 DirectoryInfo dicInfo = new DirectoryInfo(sourcePath); if (Directory.Exists(Path.GetDirectoryName(sourcePath))) { FileInfo[] files = dicInfo.GetFiles(); foreach (FileInfo file in files.OrderBy(f => int.Parse(f.Name))) { FileStream addFile = new FileStream(targetPath, FileMode.AppenFileAccess.Write); BinaryWriter AddWriter = new BinaryWriter(addFile); //获得上传的分片数据流 Stream stream = file.Open(FileMode.Open); BinaryReader TempReader = new BinaryReader(stream); //将上传的分片追加到临时文件末尾 AddWriter.Write(TempReader.ReadBytes((int)stream.Length)); //关闭BinaryReader文件阅读器 TempReader.Close(); stream.Close(); AddWriter.Close(); addFile.Close(); TempReader.Dispose(); stream.Dispose(); AddWriter.Dispose(); addFile.Dispose(); } } }
相關推薦:
以上是JS和WebService大檔案上傳程式碼分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!