I believe that uploading files through the Server Control of Asp. Net is not easy. It is not difficult to achieve the upload progress through the AjaxToolkit control. Why do I have to work hard? I do not deny "come-as-you-go", but I personally prefer what I want to do. This article describes how to implement file upload and upload progress through Html, IHttpHandler, and IHttpAsyncHandler.
:
Knowledge points involved in this article:
1. Html, Ajax, JQuery, and JQuery UI are used at the front end.
2. The background uses the IHttpHandler and IHttpAsyncHandler, and involves the "Push mode".
1. Create an Html webpage
1. upload an HTML file named uploadfile.htm in the created webproject, and introduce JQuery and JQuery UI in the header file.
Copy codeThe Code is as follows: <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. About the upload of Brushless newest files
Files cannot be uploaded through Ajax, and the hidden iframe is used for non-refreshing uploads.
Copy codeThe Code is as follows: <form id = "form" target = "frameFileUpload" enctype = "multipart/form-data">
<Div id = "progressBar" style = "font-size: 1em;"> </div>
<Input type = "file" id = "fileUpload" name = "fileUpload"/> <span id = "progressValue"> </span>
<Iframe id = "frameFileUpload" name = "frameFileUpload" style = "display: none;"> </iframe>
<Br/>
<Input type = "submit" value = "Upload" id = "submit"/>
</Form>
To set the target attribute of the form tag to the iframe id, do not forget to set the enctype of form to multipart/form-data.Copy codeThe Code is as follows: <div id = "progressBar" style = "font-size: 1em;"> </div>
Is used to display the progress bar when uploading files
Add the following processing in JS:
Copy codeThe Code is as follows: <script type = "text/javascript">
$ (Function (){
$ ("# Submit"). button ();
$ ("# FileUpload"). button ();
});
</Script>
Effect:
Ii. Implement File Upload
Add a general handler named UploadFileHandler. ashx
Copy codeThe Code is as follows: public void ProcessRequest (HttpContext context)
{
// If the submitted file name is null, it will not be processed
If (context. Request. Files. Count = 0 | string. IsNullOrWhiteSpace (context. Request. Files [0]. FileName ))
Return;
// Get the file stream
Stream stream = context. Request. Files [0]. InputStream;
// Obtain the file name
String fileName = Path. GetFileName (context. Request. Files [0]. FileName );
// Declare a byte array
Byte [] buffer;
// Why 4096? This is the minimum allocated space in the operating system. If your file contains only 100 bytes, the occupied space is actually 4096 bytes.
Int buffer size = 4096;
// Obtain the total length of the uploaded file stream
Long totalLength = stream. Length;
// Number of bytes written for upload
Long writtenSize = 0;
// Create a file
Using (FileStream fs = new FileStream (@ "C: \" + fileName, FileMode. Create, FileAccess. Write ))
{
// If the number of bytes written to the file is smaller than the total number of bytes uploaded, write the file until it is written.
While (writtenSize <totalLength)
{
// If the remaining bytes are not smaller than the minimum allocated space
If (totalLength-writtenSize> = bufferSize)
{
// Create a new byte array with the minimum allocated space
Buffer = new byte [bufferSize];
}
Else
// Create a byte array with the remaining bytes
Buffer = new byte [totalLength-writtenSize];
// Read the uploaded file to the byte array
Stream. Read (buffer, 0, buffer. Length );
// Write the read byte array to the new file stream
Fs. Write (buffer, 0, buffer. Length );
// Increase the number of written bytes
WrittenSize + = buffer. Length;
// Calculate the percentage of the currently uploaded files
Long percent = writtenSize * 100/totalLength;
}
}
}
Add the action and method attributes to the form.Copy codeThe Code is as follows: <form action = "UploadFileHandler. ashx" method = "post" id = "form" target = "frameFileUpload" enctype = "multipart/form-data">
This completes the file upload.
3. display the File Upload progress
My ideas:
During the process of file upload, information cannot be transmitted back to the client during the process. Only after all the processes are completed will the information be sent back to the client, therefore, if the context is written in the preceding handler. response. write (percent); it is impossible to get the processing process. The client can only get all the values at a time after the processing is completed.
To obtain the value in the processing process, we can solve this problem. When uploading a file, we need to enable another request to obtain the progress information. This request is asynchronous. I mean the client asynchronous request and the service end asynchronous processing. Because the transfer of information between two different request handlers is involved, the progress information obtained by the "program for processing file uploads" is passed to the "program for processing progress requests ", the "processing progress request processing program" depends on "processing file upload processing program ". Processing diagram:
First, the client sends two requests at the same time (almost), one being file upload and the other being progress requests. Because the "program that processes the request progress" is asynchronous, when the program has no information to send to the client, we make it in a waiting state, which is a bit like Tcp, in this way, the client and the server are always connected. When the "processing file upload program" starts to process, it assigns the progress value to the asynchronous operation status of the "Processing request PROGRESS program, and trigger the "program that processes the request progress" returned value to the client. The client obtains and processes the progress value. This is the end of a request with a progress value. We know that the server will not send messages to the client. The server will only respond to the client request. Obviously, if you want to send progress information to the client during file storage, each time the client gets a return result, it is a request. In order to obtain the continuous request value, the client sends a request to the "program that processes the request progress" and cyclically knows that the file upload is complete.
Technical implementation:
The IHttpAsyncHandler interface is used for asynchronous processing. Create a general processing program named RequestProgressAsyncHandler. ashx and change the default Interface to IHttpAsyncHandler.
Copy codeThe Code is as follows: public class RequestProgressAsyncHandler: IHttpAsyncHandler
{
Public void ProcessRequest (HttpContext context)
{
}
Public bool IsReusable
{
Get
{
Return false;
}
}
# Region IHttpAsyncHandler Member
Public IAsyncResult BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
{
Throw new NotImplementedException ();
}
Public void EndProcessRequest (IAsyncResult result)
{
Throw new NotImplementedException ();
}
# Endregion
}
BeginProcessRequest and EndProcessRequest are two core methods. The other two do not need to be processed. When the handler processes the request, BeginProcessRequest is the first called function and returns an object containing asynchronous state information. This object is of the IAsyncResult type and is the key to asynchronous implementation, it is used to control when the EndProcessRequest is called to end the waiting state of the processing program. After BeginProcessRequest is called, the program is in the waiting state. EndProcessRequest is the processing function at the end of the request, through which information can be written to the client.
Implementation interface IAsyncResult
Copy codeThe Code is as follows: public class AsyncResult: IAsyncResult
{
// Indicates the asynchronous processing status
Private bool isComplete = false;
// Save the Http context in the asynchronous processing program
Private HttpContext context;
// Asynchronous callback delegate
Private AsyncCallback callback;
/// <Summary>
/// Obtain or set the percentage value for saving the downloaded object
/// </Summary>
Public long PercentNumber;
Public AsyncResult (HttpContext context, AsyncCallback callback)
{
This. context = context;
This. callback = callback;
}
/// <Summary>
/// Write information to the client
/// </Summary>
Public void Send ()
{
This. context. Response. Write (PercentNumber );
}
/// <Summary>
/// Complete asynchronous processing and end the request
/// </Summary>
Public void DoCompleteTask ()
{
If (callback! = Null)
Callback (this); // The EndProcessRequest function in the processing program is triggered to end the request.
This. isComplete = true;
}
# Region IAsyncResult Member
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
}
Modify the RequestProgressAsyncHandler. ashx file:
Copy codeThe Code is as follows: public class RequestProgressAsyncHandler: IHttpAsyncHandler
{
/// <Summary>
/// Save the set of asynchronous processing status information
/// </Summary>
Public static List <AsyncResult> AsyncResults = new List <AsyncResult> ();
Public void ProcessRequest (HttpContext context)
{
}
Public bool IsReusable
{
Get
{
Return false;
}
}
# Region IHttpAsyncHandler Member
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)
{
// Ensure that only one element is used in the set.
AsyncResults. Clear ();
AsyncResult ar = (AsyncResult) result;
Ar. Send ();
}
# Endregion
}
Add the following code in UploadFileHandler. ashx:
Copy codeThe Code is as follows: private static void SendPercentToClient (long percent)
{
// After the upload is complete, ensure that the processing program can return data to the client.
While (RequestProgressAsyncHandler. AsyncResults. Count = 0 & percent = 100)
{
}
// Because this processing program and the "Processing request PROGRESS program" are concurrent, The RequestProgressAsyncHandler. AsyncResults must contain subitems.
If (RequestProgressAsyncHandler. AsyncResults. Count! = 0)
{
RequestProgressAsyncHandler. AsyncResults [0]. PercentNumber = percent;
RequestProgressAsyncHandler. AsyncResults [0]. DoCompleteTask ();
}
}
Add the preceding method to the ProcessRequest function:
Copy codeThe Code is as follows :...
...
// Calculate the percentage of the currently uploaded files
Long percent = writtenSize * 100/totalLength;
SendPercentToClient (percent );
Server OK! Modify the client and add the JS handler:
Copy codeThe Code is as follows: function RequestProgress (){
$. Post ("RequestProgressAsyncHandler. ashx", function (data, status ){
If (status = "success "){
$ ("# ProgressValue"). text (data + "% ");
Data = parseInt (data );
$ ("# ProgressBar"). progressbar ({value: data}); // set the progress bar value in JQuery UI
// If the progress is not 100, request again
If (data! = 100 ){
RequestProgress ();
}
}
});
}
Add the event omsubmit handler to form as RequestProgress.
Copy codeThe Code is as follows: <form action = "UploadFileHandler. ashx "onsubmit =" RequestProgress (); "method =" post "id =" form "target =" frameFileUpload "enctype =" multipart/form-data ">
Additional points:
1. By default, the size of files uploaded by Asp. Net is 4 MB. You can modify the size limit in Web. config.
Copy codeThe Code is as follows: <system. web>
<HttpRuntime maxRequestLength = "444444"/>
</System. web>
The unit of maxRequestLength is KB.
2. In the IE 8.0 test, after the file is uploaded, the status bar is still in the request.
There are no requests in the background. You can rest assured that you only need to move the mouse a few times back and forth between the buttons and browsing. This may be a problem with JQuery UI. FF and Chrom do not have this problem, that is, the display effect will be a little bad, but the upload is OK.
Source code download: UploadFileDemo.rar