您好,登錄后才能下訂單哦!
這篇文章給大家介紹Asp.Net中怎么實現(xiàn)無刷新文件上傳,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
一、創(chuàng)建Html網(wǎng)頁
1、在創(chuàng)建的Web工程中添加一個Html文件,命名為UploadFile.htm,在頭文件中引入JQuery,JQuery UI
復(fù)制代碼 代碼如下:
<link href="Styles/jquery-ui-1.8.16.custom.css" rel="stylesheet" type="text/css" />
<script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
2、關(guān)于無刷新文件上傳
通過Ajax是不能上傳文件的,無刷新上傳是靠隱藏的iframe來實現(xiàn)的
復(fù)制代碼 代碼如下:
<form id="form" target = "frameFileUpload" enctype="multipart/form-data">
<div id="progressBar" ></div>
<input type="file" id="fileUpload" name="fileUpload" /><span id="progressValue"></span>
<iframe id="frameFileUpload" name="frameFileUpload" ></iframe>
<br />
<input type="submit" value="上傳" id = "submit"/>
</form>
要將form標簽的target屬性設(shè)置為iframe的id,當(dāng)然別忘了將form的enctype設(shè)置為multipart/form-data
復(fù)制代碼 代碼如下:
<div id="progressBar" ></div>
是用來顯示上傳文件時的進度條
在JS中加入如下處理:
復(fù)制代碼 代碼如下:
<script type="text/javascript">
$(function () {
$("#submit").button();
$("#fileUpload").button();
});
</script>
此時效果:
二、實現(xiàn)文件上傳
添加一個一般處理程序,命名為UploadFileHandler.ashx
復(fù)制代碼 代碼如下:
public void ProcessRequest(HttpContext context)
{
//如果提交的文件名是空,則不處理
if (context.Request.Files.Count == 0 || string.IsNullOrWhiteSpace(context.Request.Files[0].FileName))
return;
//獲取文件流
Stream stream = context.Request.Files[0].InputStream;
//獲取文件名稱
string fileName = Path.GetFileName(context.Request.Files[0].FileName);
//聲明字節(jié)數(shù)組
byte[] buffer;
//為什么是4096呢?這是操作系統(tǒng)中最小的分配空間,如果你的文件只有100個字節(jié),其實它占用的空間是4096個字節(jié)
int bufferSize = 4096;
//獲取上傳文件流的總長度
long totalLength = stream.Length;
//已經(jīng)寫入的字節(jié)數(shù),用于做上傳的百分比
long writtenSize = 0;
//創(chuàng)建文件
using (FileStream fs = new FileStream(@"C:\" + fileName, FileMode.Create, FileAccess.Write))
{
//如果寫入文件的字節(jié)數(shù)小于上傳的總字節(jié)數(shù),就一直寫,直到寫完為止
while (writtenSize < totalLength)
{
//如果剩余的字節(jié)數(shù)不小于最小分配空間
if (totalLength - writtenSize >= bufferSize)
{
//用最小分配空間創(chuàng)建新的字節(jié)數(shù)組
buffer = new byte[bufferSize];
}
else
//用剩余的字節(jié)數(shù)創(chuàng)建字節(jié)數(shù)組
buffer = new byte[totalLength - writtenSize];
//讀取上傳的文件到字節(jié)數(shù)組
stream.Read(buffer, 0, buffer.Length);
//將讀取的字節(jié)數(shù)組寫入到新建的文件流中
fs.Write(buffer, 0, buffer.Length);
//增加寫入的字節(jié)數(shù)
writtenSize += buffer.Length;
//計算當(dāng)前上傳文件的百分比
long percent = writtenSize * 100 / totalLength;
}
}
}
在form中添加action和method屬性,修改之后的
復(fù)制代碼 代碼如下:
<form action="UploadFileHandler.ashx" method="post" id="form" target = "frameFileUpload" enctype="multipart/form-data">
這樣文件上傳就完成了。
三、實現(xiàn)文件上傳的進度顯示
我的思路:
文件上傳的處理過程中,是不可以在處理過程中將信息傳回客戶端的,只有當(dāng)所有的處理都完畢之后才會傳回客戶端,所以如果是在上面的處理程序中寫 入context.Response.Write(percent);是不可能得到處理的過程,只能等到處理結(jié)束后,客戶端一次性得到所有的值。
要想得到處理過程中的值,我的解決是這樣,在文件上傳時,要開啟另一個請求,來獲取進度信息。而這個請求是異步的,我指的是客戶端異步請求和服 務(wù)端異步處理。因為要涉及到兩個不同的請求處理程序之間信息的傳遞,將"處理文件上傳的程序"得到的進度信息傳遞給"處理進度請求的程序",而"處理進度 請求的處理程序"要依賴于"處理文件上傳的處理程序"。處理圖:
首先客戶端同時(幾乎是)發(fā)出兩個請求,一個是文件上傳,一個是進度請求。由于"處理請求進度的程序"是異步處理的,當(dāng)該程序沒有信息發(fā)給客戶 端時,我們讓它處于等待狀態(tài),這里有點像Tcp,這樣客戶端跟服務(wù)器就一直處于連接狀態(tài)。當(dāng)"處理文件上傳的程序"開始處理時,通過把進度值賦值給"處理 請求進度程序"的異步操作的狀態(tài),并觸發(fā)"處理請求進度的程序"返回值給客戶端。客戶端獲取進度值,并處理。這樣一次請求進度值的請求就結(jié)束了,我們知道 服務(wù)器是不會主動給客戶端發(fā)送信息的,只有客戶端請求,服務(wù)器才會響應(yīng)。顯然,要想在文件保存的過程中向客戶端發(fā)送進度信息,客戶端得到每得到一個返回結(jié) 果,都是一次請求。為了得到連續(xù)的請求值,客戶端再向"處理請求進度的程序"發(fā)出請求,依次循環(huán),知道文件上傳結(jié)束。
技術(shù)實現(xiàn):
異步處理用到接口IHttpAsyncHandler,新建一個一般處理程序,命名為RequestProgressAsyncHandler.ashx,將默認的接口改為IHttpAsyncHandler
復(fù)制代碼 代碼如下:
public class RequestProgressAsyncHandler : IHttpAsyncHandler
{
public void ProcessRequest(HttpContext context)
{
}
public bool IsReusable
{
get
{
return false;
}
}
#region IHttpAsyncHandler 成員
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
throw new NotImplementedException();
}
public void EndProcessRequest(IAsyncResult result)
{
throw new NotImplementedException();
}
#endregion
}
BeginProcessRequest和EndProcessRequest是兩個核心的方法,其他的兩個不用處理。當(dāng)該處理程序處理請求 時,BeginProcessRequest是第一個被調(diào)用的函數(shù),返回一個包含異步狀態(tài)信息的對象,該對象是IAsyncResult類型,是實現(xiàn)異步 的關(guān)鍵,用于控制什么時候調(diào)用EndProcessRequest來結(jié)束處理程序的等待狀態(tài),BeginProcessRequest被調(diào)用之后,程序就 處于等待狀態(tài)。EndProcessRequest是在結(jié)束請求時的處理函數(shù),通過該函數(shù)可以向客戶端寫入信息。
實現(xiàn)接口IAsyncResult
復(fù)制代碼 代碼如下:
public class AsyncResult : IAsyncResult
{
// 標示異步處理的狀態(tài)
private bool isComplete = false;
//保存異步處理程序中的Http上下文
private HttpContext context;
//異步回調(diào)的委托
private AsyncCallback callback;
/// <summary>
/// 獲取或設(shè)置保存下載文件的百分比數(shù)值部分
/// </summary>
public long PercentNumber;
public AsyncResult(HttpContext context, AsyncCallback callback)
{
this.context = context;
this.callback = callback;
}
/// <summary>
/// 向客戶端寫入信息
/// </summary>
public void Send()
{
this.context.Response.Write(PercentNumber);
}
/// <summary>
/// 完成異步處理,結(jié)束請求
/// </summary>
public void DoCompleteTask()
{
if (callback != null)
callback(this);//會觸發(fā)處理程序中的EndProcessRequest函數(shù),結(jié)束請求
this.isComplete = true;
}
#region IAsyncResult 成員
public object AsyncState
{
get { return null; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { return null; }
}
public bool CompletedSynchronously
{
get { return false; }
}
public bool IsCompleted
{
get { return isComplete; }
}
#endregion
}
修改 RequestProgressAsyncHandler.ashx文件:
復(fù)制代碼 代碼如下:
public class RequestProgressAsyncHandler : IHttpAsyncHandler
{
/// <summary>
/// 保存異步處理狀態(tài)信息的集合
/// </summary>
public static List<AsyncResult> AsyncResults = new List<AsyncResult>();
public void ProcessRequest(HttpContext context)
{
}
public bool IsReusable
{
get
{
return false;
}
}
#region IHttpAsyncHandler 成員
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
AsyncResult result = new AsyncResult(context, cb);
AsyncResults.Add(result);
return result;
}
public void EndProcessRequest(IAsyncResult result)
{
//保證集合中只用一個元素
AsyncResults.Clear();
AsyncResult ar = (AsyncResult)result;
ar.Send();
}
#endregion
}
在UploadFileHandler.ashx添加如下代碼:
復(fù)制代碼 代碼如下:
private static void SendPercentToClient(long percent)
{
//當(dāng)上傳完畢后,保證處理程序能向客戶端傳回
while (RequestProgressAsyncHandler.AsyncResults.Count == 0 && percent == 100)
{
}
//因為本處理程序和"處理請求進度的程序"是并發(fā)的,不能保證RequestProgressAsyncHandler.AsyncResults一定含有子項
if (RequestProgressAsyncHandler.AsyncResults.Count != 0)
{
RequestProgressAsyncHandler.AsyncResults[0].PercentNumber = percent;
RequestProgressAsyncHandler.AsyncResults[0].DoCompleteTask();
}
}
在函數(shù)ProcessRequest中加入以上方法:
復(fù)制代碼 代碼如下:
...
...
//計算當(dāng)前上傳文件的百分比
long percent = writtenSize * 100 / totalLength;
SendPercentToClient(percent);
服務(wù)端OK!修改客戶端,添加JS處理函數(shù):
復(fù)制代碼 代碼如下:
function RequestProgress() {
$.post("RequestProgressAsyncHandler.ashx", function (data, status) {
if (status == "success") {
$("#progressValue").text(data + "%");
data = parseInt(data);
$("#progressBar").progressbar({ value: data });//JQuery UI 設(shè)置進度條值
//如果進度不是 100,則重新請求
if (data != 100) {
RequestProgress();
}
}
});
}
在form中添加事件omsubmit的處理函數(shù)為RequestProgress
復(fù)制代碼 代碼如下:
<form action="UploadFileHandler.ashx" onsubmit = "RequestProgress();" method="post" id="form" target = "frameFileUpload" enctype="multipart/form-data">
補充幾點:
1.默認Asp.Net允許的上傳文件的大小是4M,可以在Web.config中修改其大小限制
復(fù)制代碼 代碼如下:
<system.web>
<httpRuntime maxRequestLength="444444"/>
</system.web>
maxRequestLength的單位是KB
2.在IE 8.0測試中,在文件上傳完畢后,狀態(tài)欄還處于請求中
關(guān)于Asp.Net中怎么實現(xiàn)無刷新文件上傳就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。