Home.NET HTTP File Upload without User Interaction ...
HTTP File Upload without User Interaction using .NET
This article aims to teach users how to upload files by using .NET without getting messy, as can happen with HTTP. The author looks at possible solutions and explains why they do not work, then goes on to outline his solution.
This article addresses the problem of uploading a file without user interaction, similar to an article I previously wrote, "HTTP File Download without user interaction using .NET". Most of the upload code available depends on the user to browse his or her hard disk to select the file (based on RFC1867), and it doesn’t display a progress bar while uploading it to the server. This article provides an appropriate solution for it.
Concept
The idea is to have an ActiveX control (for other alternatives, read the download article noted above) read the file from the client's hard disk and write it into the Request stream of HTTP. The ASP.NET code on the server will read the file content from the Request stream and write it into the hard disk.
About ActiveX Control
The term 'ActiveX' refers to an extension of existing OLE and COM technologies. An ActiveX control is an object that supports a customizable, programmatic interface. Using the methods, events, and properties exposed by a control, Web authors can automate their HTML pages. Examples of such controls include text boxes, command buttons, audio players, video players, stock tickers, and so on.
The following are the possible solutions which can be used to solve our problem.
INET control - This is an ActiveX control provided by Microsoft for Internet transfer of files. We can read the file contents into a string and send it as POST data using the function Execute provided by the control. If all you want to do is upload the file, then this method should suffice, but if you want to display the progress as well, then this solution can't be used as it doesn’t provide the number of bytes being uploaded.
Wininet dll - This DLL contains a set of APIs provided by Microsoft for Internet transfer of files. Performance is better in this case since we are directly using the APIs and not relying on another control to provide the functionality. This is the DLL which I used for downloading the file but sadly for uploading the file, it has a bug (it always returns 0 when it should return 1) in its InternetWriteFile function.
Winsock control - This is an ActiveX control provided by Microsoft for network programming. It uses sockets to connect to the server and get the files. It’s a low level control where the programmer has to do the bulk of the work, but luckily it provides sendProgress event which gives information about the number of bytes uploaded. So we would be using this control to solve our problem.
Create a new ASP.NET project with VB.NET as code behind and name it as MyUpload.
Add a new webform called upload.aspx and paste this piece of code in the aspx file page_load procedure.
Private Sub Page_Load( ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim buff() as byte Dim fw As System.IO.FileStream = New System.IO.FileStream("c:\\upload.doc", IO.FileMode.Create) buff = Request.BinaryRead(Request.TotalBytes) fw.Write(buff, 0, buff.Length) fw.Close() End Sub
The above code reads the file content into a byte array called buff and then writes buff into a file using FileStream. It's very important and a good programming practice to close the file stream after using it.
Build the project and it's all set as far as the server side code is concerned.
Client Side Code
Create a new ActiveX control VB project called FileUpload.
Change the name of the user control to FileUploadCtrl.
Add a frame to the user control and place the following labels, progress bar inside the frame and WinSock Control.
lblByteU - set its caption to "Bytes Uploaded".
lblBytesUploaded - set its caption to "".
lblFileS - set its caption to "FileSize in Bytes".
lblFileSize - set its caption to "".
pgUpload - set progressbar name to "pgUpload"
wsUpload - set WinSock control name to "wsUpload"
Use the "ActiveX control interface wizard" in VB6's add-in menu to create functions with following declaration:
Public Function Connect(strServerName As String, ByRef errno As integer) As Boolean
Parameters
strServerName- Name of the server to connect to eg localhost.
errno- Gives the errno if any error has occurred.
Returns
True or False depending on whether the operation was success or not.
Public Function UploadFile(url As String, filename As String, ByRef errno As integer) As Boolean
Parameters
url - is the url of your upload.aspx file e.g. http://localhost/MyUpload/upload.aspx
filename- is the name of the file to upload
errno- gives the errorno if any error has occurred Returns
True or false depending on whether the operation was success or not
Public Function Disconnect(ByRef errno As Integer) As Boolean Parameters
errno- gives the errorno if any error has occurred Returns
True or false depending on whether the operation was success or not
Once you have completed the wizard, Locate Connect function in the code and add these statements.
Open strFileName For Binary As #2 strData = Input(FileLen(strFileName), #2) Close #2
Construct the HTTP Request packet, by first creating the header of the packet giving the protocol being used for sending the request. We will be using POST to send data due to its support of large volume of data. We also specify the content type of the data and what’s the length of the data
Complete the HTTP Request packet by appending the data payload.
strPostData = strPostData & strData & vbCrLf
Now all we need to do is send the Post Data through the Winsock control and complete error handling section
wsUpload.SendData strPostData
UploadFile = True
Exit Function errhandle: nErrNo = Err.Number UploadFile = False
Copy the following lines of code to implement the progress bar functionality.
'This event is fired once the data has been sent completely Private Sub wsUpload_SendComplete() lngTotalBytesSent = 0 lblBytesUploaded.Caption = lngFileLen pgUpload.Value = 100 End Sub
'This event is fired once the sendData function is called Private Sub wsUpload_SendProgress(ByVal bytesSent As Long, ByVal bytesRemaining As Long) Dim nPercent As Integer lngTotalBytesSent = lngTotalBytesSent + bytesSent nPercent = Int((lngTotalBytesSent / lngFileLen) * 100) pgUpload.Value = nPercent lblBytesUploaded.Caption = lngTotalBytesSent lblBytesUploaded.Refresh pgUpload.Refresh End Sub
7. With the above steps, we have finished the code for uploading the files. Now only the creation of the activex control remains. To create it, click on File menu of VB IDE and there will be a selection called "make fileupload.ocx", click on it and Voila, your activex control is ready.
8. In order for the control to be downloaded over the Internet, we need to package it into CAB file. This can be done with the help of "Package and Deployment Wizard" provided Visual Studio6.
9. The wizard would generate a CAB file and htm file. Copy these 2 files to your webserver's virtual directory and write a small javascript function in the htm file which would call the control's uploadFile method. Eg
<script language=javascript> function upload() { var b,errno,errdesc,errsrc; FileUploadCtrl.uploadFile("http://localhost/Myupload/upload.aspx", "c:\\uploads\\uploadFile.doc",errno); } </script>
10. The one thing that you have to keep in mind is you need to sign the activex control for it to be installed on the client machine without changing the security settings of Internet Explorer.
If you are planning to give an uninstalled activex control then on the client machine' Internet Explorer, you've got to go to internet options->security->internet and reduce it to the lowest level.
Conclusion
In this article, we have seen how to write our own custom code to upload a file over the Internet. And I hope I have answered the questions of many people who have queried me on how to write the upload control.