1. Technology
Uploading files to a web server with ASP.Net
Let's enable uploading of binary files from a client browser to the web server in ASP.Net web applications.
 Win prizes by sharing code!
Do you have some Delphi code you want to share? Are you interested in winning a prize for your work?
Delphi Programming Quickies Contest
 Join the Discussion
"Post your views and comments to this chapter of the free Asp.Net Delphi Programming Course"
Discuss!
 Related Resources
• A Beginner's Guide to Asp.Net Programming for Delphi developers.TOC
• How to enable file download from an Asp.net page
 Elsewhere on the Web
• About HTML

Welcome to the ninth chapter of the FREE online programming course:
A Beginner's Guide to Asp.Net Programming for Delphi developers.
Delphi for .Net and ASP.NET provide an easy way to accept files from the client using HTMLInputFile ("HTML File Upload" HTML server control) and HTTPPostedFile classes.

Most ASP.Net applications and sites enable users to upload files from the client's computer to the web server. You can find typical file upload features in content management Web sites and applications that allow customization based on the uploaded files - after all the BDSWebExample provides an option to send an image of the product to be included in the product listing.

HTMLInputFile
ASP.NET easily allows developers to provide file upload support. On the server side, ASP.NET offers this functionality by means of an HTML server control called HtmlInputFile, which manages the upload for you. An instance of this class can be created and used easily through an ASP.NET Web page in just a few lines of code. The HtmlInputFile control enables programming of the HTML <input type=file> element. Recall that in the previous chapter we mentioned this component and that it can be located in the "HTML Elements" group on the Tool Palette window under the name: "HTML File Upload".

Setting up a web form for file uploading.
Enabling uploading a file using the HTMLInputFile is a few-steps process:

HTML Input file in aspx view 1. While previewing your web form (in design view), add a "HTML File Upload" control from the "HTML Elements" group on the Tool Palette.

2. Switch to the "aspx" view and add the "runat=server" attribute to the newly created <input type=file> element. This allows you to manipulate the control in web form's code-behind file.

3. Assign a name for your control by adding an "id" attribute such as "FileUpload". The input element now looks like: <input id=FileUpload type=file runat="server">

4. Activate the code editor and add the control declaration to the "strict-protected" section part of the TWebForm1 (if this is the name of your form's class), like:
FileUpload : System.Web.UI.HtmlControls.HtmlInputFile;

5. And finally, it is very important that the (server-side) form tag includes the enctype="Multipart/Form-Data" attribute. Note that if you are building your page dynamically, you might want to ensure the proper form encoding from code: How to programmatically change the enctype attribute (to "Multipart/Form-Data"" for example) of an ASP.Net web form.

The resulting HTML rendered by this control (when requested by a visitor) is simply an input tag with its type set to file. This Html tag has the effect of displaying a textbox with a Browse button next to it. When the user presses the Browse button, a "Choose file" dialog gets displayed allowing the user to select the file to upload.

HTML File Upload in Browser

Select (client), receive and save (server) the uploaded file.
The actual save operation is usually done in an event-handling method, such as for a button click. In order to process the file on the server you need to add a Button web server control to a web form and handle its Click event.

Note 1: we are yet to discuss ASP.Net Web Controls in this course. For now, let's just say that a Button web control acts much similar to a standard button in desktop development.

Note 2: This time don't pick the "HTML Button" (HTML Control), use "Button" (Web Control) control instead.

Activate the design view, locate the Button component on the Tool Palette (Web Control group) and drop it on the form, let it have the "UploadButton" ID ("ID" property = "Name" property in Win32). Change the Text property to "Upload" ("Text" property == "Caption" property in Win32). Create a procedure to handle the button click by double clicking on the button - this action activates the code editor and creates a skeleton for you to add the code. When the button is clicked (by a user visiting your page/site), the form is submitted and the server-side event handler UploadButton_Click is executed.

The following example shows a simple file upload processing. When the user clicks the Upload button on the form, the message is displayed using the Mono Dialogs package, while the file itself is uploaded to a specified directory on the server.

uses System.IO, ...

...

TWebForm1 = class(System.Web.UI.Page) ... strict protected FileUpload:System.Web.UI.HtmlControls.HtmlInputFile; UploadButton:System.Web.UI.WebControls.Button; ... procedure TWebForm2.UploadButton_Click (sender: System.Object; e: System.EventArgs); const ServerSavePath = 'c:\MySite\Upload'; var ClientFileName : string; ServerFileName : string; UploadOK : boolean; begin //make sure the client selected an existing file if (not Assigned(FileUpload.PostedFile)) OR (FileUpload.PostedFile.FileName.Length = 0) OR (FileUpload.PostedFile.ContentLength = 0) then begin Dialogs.ShowMessage( Self, 'No file selected to upload!', 'Warning', TDlgType.mtWarning, 200); Exit; end; (*save the file to the server*) ClientFileName := Path.GetFileName (FileUpload.PostedFile.FileName); ServerFileName := // or GetUniqueFileName(...) Path.Combine (ServerSavePath, ClientFileName); UploadOK := True; try FileUpload.PostedFile.SaveAs(ServerFileName); except on Ex:Exception do begin UploadOK := False; Dialogs.ShowMessage( Self, 'An error occured while saving the file to the server!' + #13#10 + Ex.ToString, 'Error', TDlgType.mtError, 0); end; end; if UploadOK then Dialogs.ShowMessage( Self, 'File successfully uploaded to the web server!', 'Upload', TDlgType.mtInformation, 200); end;

The HtmlInputFile control does not have a built-in way to post back to the server nor to save the file. To actually store the file on the server we use the PostedFile property, which represents an uploaded file. PostedFile is an HttpPostedFile object and provides properties and methods to get information on an individual file and to read and save the file.

In general, all the above code handles four simple tasks.

  • Firstly, we need to make sure the user has picked a file to upload. This is done by evaluating FileUpload.PostedFile.FileName.Length = 0.
  • Secondly, we extract the name of the file that is to be uploaded, the Path.GetFileName call is used for this task - where GetFileName is a static method of the Path class (defined in the System.IO namespace).
  • Next, we create a file name to be saved on the server - note that we used the ServerSavePath constant for this. The file on the server will have the same name as the file the user picked, *only* the location (path) is different. Path.Combine call is used to ensure the ServerFileName represents a valid file name.
  • Finally, SaveAs method of the HttpPostedFile class is used to actually save the file on the server. Note that an error catching block is used to provide a user-friendly message of the result of the file upload action.

    Note: by using the Dialogs package we provide much more user-friendly feedback to our visitors. If you do not use MonoSoftware.Dialogs you could add a Label web control to the form and use it for message-displaying purposes.

    HttpPostedFile
    As you can see, the HTMLInputFile gives us the HTML, but the actual work is done using the HttpPostedFile class. If the user has selected a file for upload, then FileUpload.PostedFile is a valid HttpPostedFile object. The HttpPostedFile provides several interesting properties:

    ContentLength – size of the uploaded file in bytes,
    FileName – full path to uploaded file on client's system, i.e. c:\ClientFolder\UserPicture.gif,
    ContentType – MIME type of uploaded file, i.e. "image/gif",
    InputStream – a System.IO.Stream pointing to the uploaded file.

    You can use, for example, the ContentLength property to "reject" all the files larger than 512 Kb, here's how:

     with FileUpload.PostedFile 
      if ContentLength > 1024 * 512 then
        //Exit the proc and notify the user that only
        //files up to 512 Kb can be uploaded.
    

    What can go wrong...
    1. The Enctype property of an HtmlForm must be set to "multipart/form-data" for this control to work properly.
    2. When you use the SaveAs method, make sure to specify the full (existing) path to the file on the server. If you only specify the file name, ASP.Net will try to save the file in the systemroot\system32\inetsrv directory.
    3. What's more, if you get an "access denied" error when trying to save the file, make sure that your ASPNET, guest, or impersonated accounts have appropriate (write) permissions. (To change this, right-click on the folder, select Sharing and Security, and then select the Security tab.)
    4. If there is a file on the server with the same name as the one user is uploading, the above code will overwrite the existing one. You might want to create a unique name for the file before saving it.
    Here's a sample function that will return a unique name (on the server) for the file being uploaded (it simply prefixes the file name with the "_" character - as many times as needed):

    function GetUniqueFileName
       (ServerSavePath, fileName:string):string;
    begin
     while 
       Path.FileExists(
          Path.Combine(
             ServerFolder,fileName)) do
      fileName := '_' + fileName;
    		
     Result := Path.Combine(ServerFolder,fileName);
    end;
    

    For example: if the file name being uploaded is "myfile.zip" and there already is a file with the same name on the server in the ServerSavePath folder, the GetUniqueFileName will return ServerSavePath + "_myfile.zip" - or "c:\MySite\Upload\_myfile.zip"

    You can use this function in the above code as:

    ...
      ServerFileName := 
          GetUniqueFileName(
               ServerSavePath, 
               ClientFileName);
    ...           
    

    Note: if you do not whish to use hard coded path on the server, but rather save the file in some subfolder of the web application's path, you should use the MapPath method of the HTTPServerUtility class. Here's an example:

      ServerSavePath := Server.MapPath('/Upload');
    

    This will return the physical path for a given virtual path. If your web application's root is under 'c:\InetPub\WWWRoot\MyWebApplication' then Server.MapPath('/Upload') would return 'c:\InetPub\WWWRoot\MyWebApplication\Upload'.

    Job done
    Now you can have all your users upload files from your pages, ... and if you want to send "files back", here's how to enable file download from an Asp.net page.

    To the next chapter: A Beginner's Guide to Asp.Net Programming for Delphi developers
    That's it for today, in the next chapter we'll continue to explore the content of a web form: HTML controls, Web control ... and who knows what else :) Stay tuned!

    If you need any kind of help at this point, please post to the Delphi Programming Forum where all the questions are answered and beginners are treated as experts.

    A Beginner's Guide to Asp.Net Programming for Delphi developers: Next Chapter >>
    >> Web Forms navigation in ASP.NET

  • ©2014 About.com. All rights reserved.