asp.net implementation of MVC processing file upload Download Function Example Tutorial _ Practical skills

Source: Internet
Author: User
Tags http request server memory

Upload in the download function is a very common function in the program design, in the ASP.net program development has very widespread application. This article takes the example form to realize this function.

I. Overview

If you only have the ASP.net Web forms background instead of learning asp.net mvc, I think your first experience may be that the service-side controls that have made your programming enjoyable are driving the crane West. FileUpload is one of them, and the absence of this control brings us some minor problems. This article mainly says how to upload files in asp.net mvc, and then how to download the uploaded files from the server.

Ii. Methods of implementation

1. File Upload

In Web Forms, when you drag a FileUpload control to the designer, you may not notice that adding an extra attribute to the form tag in the generated HTML enctype= "Multipart/form-data". The FileUpload control itself becomes <input type= "file"/>, and in MVC view there are many ways to do the same, the first HTML is as follows:

<form action= "/" method= "POST" enctype= "Multipart/form-data" > 
 <input type= "file" name= "FileUpload1"/ ><br/> <input type= "Submit" name= "submit" id= "Submit 
 " value= "Upload"/> 
</form> 

Note that the form label already includes the enctype tag, and the method property is set to "post" so that it does not have to be set more than the default commit by HTTP GET. In this way, using the Html.BeginForm () extension method generates the same HTML as the above:

<% 
 using (Html.BeginForm ("", "Home", FormMethod.Post, new {enctype= "Multipart/form-data"})  
  {%>  
   <input type= "File" Name= "FileUpload1"/><br/> <input type= " 
   submit" name= "submit" id= "Submit" value = "Upload"/> 
<%}%> 

Note the Name property of the <input type= "file" > tag, which we'll discuss later
OK, now we can browse the local file and then submit the file to the server via the Upload submit button, and the next step is to process the uploaded file on the server side, and when using the FileUpload control, You can easily see if the file is uploaded through the FileUpload HasFile method. But in asp.net mvc it seems not so convenient, you will be closer to the original HTTP, however, an extension method can handle these:

public static bool HasFile (this httppostedfilebase file) 
{return 
 (file!= null && file. ContentLength > 0)? True:false; 
}

When you see the corresponding controller class code, you will find that the request object exists as an attribute of the httprequestbase type. Httpreuqestbase is actually an encapsulation of the HTTP request, which leaks a lot of attributes, including the Files collection (actually a collection of httpfilecollectionbase), Each element in the collection is a collection of httppostedfilebase, and the extension method is used to ensure that the uploaded file exists. In fact, this works in accordance with the Fileupload.hasfile () method.

It's really easy to use in controller action:

public class Homecontroller:controller 
{public 
 actionresult Index () 
 { 
  foreach (string upload in Request.Files) 
  { 
   if (! Request.files[upload]. HasFile ()) continue; 
   String path = AppDomain.CurrentDomain.BaseDirectory + "uploads/"; 
   string filename = Path.getfilename (Request.files[upload]. FileName); 
   Request.files[upload]. SaveAs (Path.Combine (Path, filename)); 
  return View (); 
 } 

2. Multi-File Upload

Maybe you've thought earlier about how better to use Request.Files as a collection. This means that not only can it accommodate a single file, but it can accommodate multiple, we change the view above to read as follows:

<% 
 using (Html.BeginForm ("", "Home", FormMethod.Post, new {enctype= "Multipart/form-data"})  
  {%>  
   <input type= "File" Name= "FileUpload1"/><br/> <input type= " 
   file" name= "FileUpload2"/><br/ > 
   <input type= "file" Name= "FileUpload3"/><br/> <input type= " 
   file" name= "FileUpload4"/ ><br/> 
   <input type= "file" name= "FileUpload5" "/><br/> <input type= 
   " Submit "Name=" Submit "id=" Submit "value=" Upload "/> 
<%}%>  

In the controller code has checked whether all file upload boxes have files, so even for multiple file uploads, we no longer need to modify the controller code, pay attention to each <input type= "file" > have different name attributes, if you need to invoke one of them, for example, you need to refer to the third input box only to use: request.files["FileUpload3".

3. Deposit in the database

When you're screaming at me "separation of concerns", I want to declare that the following code is used only as a description function. I put ado.net code into the controller action, but as we all know, that's not good. The code for data access should be placed in the data access layer of a part of model. However, the following code can only give you a more intuitive impression of how the uploaded files are stored in the database, first, we need to create a datasheet (filetest) and create a table: Filestore

CREATE TABLE [dbo]. [Filestore] ( 
[ID] [int] IDENTITY (1,1) not NULL, 
[filecontent] [image] is not null, 
[mimetype] [nvarchar] is not NULL, 
[FileName] [nvarchar] (not NULL 
) On [PRIMARY] textimage_on [PRIMARY] 

The Filecontent field is an image data type that stores files formed from binary data, and the index action is changed to:

Public ActionResult Index () {foreach (string upload in Request.Files) {if (!) Request.files[upload]. 
  HasFile ()) continue; String mimetype = Request.files[upload]. 
  ContentType; Stream FileStream = Request.files[upload]. 
  InputStream; String fileName = Path.getfilename (Request.files[upload]. 
  FileName); int filelength = Request.files[upload]. 
  ContentLength; 
  byte[] Filedata = new Byte[filelength]; 
  FileStream.Read (filedata, 0, filelength); Const string connect = @ "Server=.\sqlexpress;database=filetest; 
  Trusted_connection=true; "; using (var conn = new SqlConnection (connect)) {var qry = ' INSERT into Filestore (filecontent, MimeType, FileName) 
   VALUES (@FileContent, @MimeType, @FileName) "; 
   var cmd = new SqlCommand (qry, conn); Cmd. 
   Parameters.addwithvalue ("@FileContent", filedata); Cmd. 
   Parameters.addwithvalue ("@MimeType", mimetype); Cmd. 
   Parameters.addwithvalue ("@FileName", FileName); Conn. 
   Open (); Cmd. 
  ExecuteNonQuery (); } return ViEW ();

 }

The modified code loops through all of the uploaded files in the Web page and checks to see if the file has been added to the <input type= "file" >, and then extracts 3 messages from the file: file name, MIME type (type of file), HTTP The binary stream in request. Binary data is converted to a byte array and stored in the database with the image data type. MIME types and file names are important for users to extract files from the database.

4. Return the files in the database to the user:

How you send the file to the user depends on how you first stored it, and if you put the file in the database, you will return the file to the user in a streaming way, and if you have the file on the hard drive, you just need to provide a hyperlink, or you can do it in a streaming way. Whenever you need to stream files to a browser, you use overloads of the file () method (instead of using the view () method that we have been using previously), there are 3 types of return type for the file () method: Filepathresult, Filecontentresult and Filestreamresult, the first type is used to return files directly from the disk; the second type is used to return the byte array to the client, and the third way to return the contents of the stream object that has been generated and opened to the client.

If you remember, we saved the uploaded file in the database and stored it in a byte array in the Filecontent domain. And when it is needed, it still extracts it as a byte array, which means we use the return Filecontentresult file ( Overload, if we want to make the extracted filename more meaningful, we use an overload that accepts 3 parameters, three are: byte array, MIME type, filename:

Public Filecontentresult GetFile (int id) 
{ 
 SqlDataReader rdr; byte[] filecontent = null;  
 String mimetype = ""; string fileName = ""; 
 Const string connect = @ "Server=.\sqlexpress;database=filetest; Trusted_connection=true; "; 
 using (var conn = new SqlConnection (Connect)) 
 { 
  var qry = ' Select Filecontent, MimeType, FileName from Filestore W Here ID = @ID "; 
  var cmd = new SqlCommand (qry, conn); 
  Cmd. Parameters.addwithvalue ("@ID", ID); 
  Conn. Open (); 
  RDR = cmd. ExecuteReader (); 
  if (RDR. HasRows) 
  { 
   rdr. Read (); 
   Filecontent = (byte[]) rdr["Filecontent"]; 
   MimeType = rdr["MimeType"]. ToString (); 
   filename = rdr["filename"]. ToString (); 
  } 
 } 
 Return File (Filecontent, MimeType, fileName); 
}  

The simplest use of this action in view is to provide only one hyperlink:

<a href= "/GETFILE/1" >click to get file</a> 

If the picture stored in the database is a picture type, and unlike using a hyperlink, we get a <image> tag with the SRC attribute pointing to the controller action:

 

Let's take a look at how easy it is to use Filepathresult (to extract files from a hard disk):

Public Filepathresult Getfilefromdisk () 
{ 
 string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/"; 
 String fileName = "Test.txt"; 
 return File (path + fileName, "Text/plain", "test.txt"); 
}  

This can also be extracted using a hyperlink:

<a href= "/getfilefromdisk" >click to get file</a> 

And the last option Filestreamresult can also extract files from disk:

Public Filestreamresult Streamfilefromdisk () 
{ 
 string path = AppDomain.CurrentDomain.BaseDirectory + "uploads /"; 
 String fileName = "Test.txt"; 
 Return File (new FileStream (path + filename, FileMode.Open), "Text/plain", filename); 
}  

Third, to supplement

What is the difference between Filepathresult and Filestreamresult? How should we choose? The main difference is that Filepathresult uses Httpresponse.transmitfile to write files to the HTTP output stream. This method does not buffer in server memory, so this is a good choice for sending large files. Their differences are much like the difference between DataReader and datasets. At the same time, TransmitFile also has a bug, which may cause the file to be passed to the client half stopped, or even unable to transfer. And Filestreamresult is great in this area. For example, returns a picture of a chart that the ASP.net Chart control generates in memory without having to save the picture to disk.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.