Asp.net实现MVC处理文件的上传下载功能实例教程

这篇文章主要介绍了Asp.net实现MVC处理文件的上传下载功能,比较全面而系统的对Asp.net MVC的文件上传下载功能进行了深入分析,有很好的借鉴价值,需要的朋友可以参考下

上传于下载功能是程序设计中非常常见的一个功能,在ASP.NET程序开发中有着非常广泛的应用。本文就以实例形式来实现这一功能。

一、概述

如果你仅仅只有Asp.net Web Forms背景转而学习Asp.net MVC的,我想你的第一个经历或许是那些曾经让你的编程变得愉悦无比的服务端控件都驾鹤西去了.FileUpload就是其中一个,而这个控件的缺席给我 们带来一些小问题。这篇文章主要说如何在Asp.net MVC中上传文件,然后如何再从服务器中把上传过的文件下载下来.

二、实现方法

1.文件上传

在Web Forms中,当你把一个FileUpload控件拖到设计器中,你或许没有注意到在生成的HTML中会在form标签中加入一条额外属性 enctype="multipart/form-data". 而FileUpload控件本身会生成为<input type=”file” />,在MVC的view里,有许多种方法可以做到同样效果,第一种的HTML如下:

?


1

2

3

4

<form action="/" method="post" enctype="multipart/form-data">

 <input type="file" name="FileUpload1" /><br />

 <input type="submit" name="Submit" id="Submit" value="Upload" />

</form>

注意form标签已经包括了enctype标签,而method属性则设为”post”,这样设置并不多于因为默认的提交时通过HTTP get方式进行的。下面这种方式,使用Html.BeginForm()扩展方法,会生成和上面同样的HTML:

?


1

2

3

4

5

6

<%

 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" />

<% }%>

注意<input type=”file”>标签的name属性,我们在后面再讨论
OK,现在我们可以浏览本地文件然后通过Upload提交按钮将文件提交到服务器端,下一步就是在服务器端处理上传的文件,在使用fileUpload控
件时,你可以很轻松的通过FileUpload的hasFile方法来查看文件是否被上传。但是在Asp.net
MVC中貌似就不是这么方便了,你会和原始的HTTP更接近一些,然而,一个扩展方法可以处理这些:

?


1

2

3

4

public static bool HasFile(this HttpPostedFileBase file)

{

 return (file != null && file.ContentLength > 0) ? true : false;

}

当你看到对应的Controller类的代码时,你会发现Request对象作为HttpRequestBase类型的一个属性存在。
HttpReuqestBase其实是HTTP请求的一个封装,暴漏了很多属性,包括Files
collection(其实是HttpFileCollectionBase的集合),在集合中的每一个元素都是HttpPostedFileBase的
集合,扩展方法是用于确保上传的文件是否存在。实际上,这和FileUpload.HasFile()方法的工作原理一致。

在Controller Action中使用起来其实很容易:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

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.多文件上传

或许你已经比我更早的想到如何更好的将Request.Files作为一个集合使用。这意味着它不仅仅只能容纳一个文件,而能容纳多个,我们将上面的View改为如下:

?


1

2

3

4

5

6

7

8

9

10

<%

 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" />

<% }%> 

在Controller的代码中已经检查了是否所有的文件上传框中都有文件,所以即使对于多文件上传,我们也不再需要修改Controller的代
码,注意每一个<input
type=”file”>都有不同的name属性,如果你需要调用其中一个,比如说,你需要引用第三个输入框只需要使
用:Request.Files["FileUpload3"].

3.存入数据库

在你冲我狂吼”关注点分离”之前,我想声明下面的代码仅仅用于作为说明功能.我将ADO.Net的代码放入Controller
action中,但我们都知道,这并不好。数据访问的代码应该放在Model中某个部分的数据访问层中.但是,下面这段代码仅仅可以给大家怎样将上传的文
件存入数据库中一个更直观的印象,首先,我们需要创建一个数据表(FileTest)并创建一个表:FileStore

?


1

2

3

4

5

6

CREATE TABLE [dbo].[FileStore](

[ID] [int] IDENTITY(1,1) NOT NULL,

[FileContent] [image] NOT NULL,

[MimeType] [nvarchar](50) NOT NULL,

[FileName] [nvarchar](50) NOT NULL

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

FileContent域是image数据类型,用于存储以二进制数据形成的文件,而Index Action改为:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

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();

}

修改后的代码会以循环的方式遍历Web页面中所有的上传文件,并检查<input
type=”file”>中是否已经加入文件,然后,从文件中提取出3个信息:文件名,MIME类型(文件的类型),HTTP
Request中的二进制流。二进制数据被转换为byte数组,并以image数据类型存入数据库。MIME类型和文件名对于用户从数据库中提取文件来说
非常重要。

4.将数据库中的文件返回给用户:

你如何将文件传送给用户取决于你最开始如何存储它,如果你将文件存入数据库,你会用流的方式将文件返还给用户,如果你将文件存在硬盘中,你只需要提
供一个超链接即可,或者也可以以流的方式。每当你需要以流的方式将文件送到浏览器中,你都的使用到File()方法的重载(而不是使用我们先前一直使用的
View()方法),对于File()方法有3类返回类型:FilePathResult,FileContentResult和
FileStreamResult,第一种类型用于直接从磁盘返回文件;第二种类型用于将byte数组返回客户端;而第三种方式将已经生成并打开的流对象
的内容返回客户端。

如果你还记得的话,我们将上传的文件存入了数据库,并以byte数组的形式存入FileContent域内.而当需要提取时,它仍然会以一个
byte数组进行提取,这意味着我们使用返回FileContentResult的File()重载,如果我们想让提取的文件名更有意义,我们使用接受3
个参数的重载,三个参数是:byte数组,MIME类型,文件名:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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 WHERE 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);

在View中最简单的使用来使用这个Action只需提供一个超链接:

?


1

<a href="/GetFile/1">Click to get file</a>

如果在数据库中存储的图片是图片类型,和使用超链接不同的是,我们通过指向Controller action的一个带有src属性的<image>标签来获取:

?


1

<img src="/GetFile/1" alt="My Image" />

下面再让我们来看看使用FilePathResult(用于从硬盘提取文件)是多简单的事:

?


1

2

3

4

5

6

public FilePathResult GetFileFromDisk()

{

 string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";

 string fileName = "test.txt";

 return File(path + fileName, "text/plain", "test.txt");

而这也可以用过超链接提取:

?


1

<a href="/GetFileFromDisk">Click to get file</a>

而最后一个选择FileStreamResult也可以从磁盘中提取文件:

?


1

2

3

4

5

6

public FileStreamResult StreamFileFromDisk()

{

 string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";

 string fileName = "test.txt";

 return File(new FileStream(path + fileName, FileMode.Open), "text/plain", fileName);

三、补充

FilePathResult和FileStreamResult的区别是什么?我们又该如何取舍呢?主要的区别是FilePathResult使
用HttpResponse.TransmitFile来将文件写入Http输出流。这个方法并不会在服务器内存中进行缓冲,所以这对于发送大文件是一个
不错的选择。他们的区别很像DataReader和DataSet的区别。于此同时,
TransmitFile还有一个bug,这可能导致文件传到客户端一半就停了,甚至无法传送。而FileStreamResult在这方面就很棒了。比
如说:返回Asp.net Chart 控件在内存中生成的图表图片,而这并不需要将图片存到磁盘中.

时间: 2024-08-04 22:18:14

Asp.net实现MVC处理文件的上传下载功能实例教程的相关文章

JavaWeb实现文件上传下载功能实例解析

转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件

JavaWeb实现文件上传下载功能实例解析 (好用)

转: 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上

asp.Net文件的上传下载(2) 转

Asp.net 上传.下载文件 2011-01-08 16:21:48|  分类: .NET |  标签: |举报 |字号大中小 订阅 首先我们要判断用户是否选择了要上传文件,我们可用下面这句实现: if(File1.PostedFile.ContentLength>0)  如果用户有上传的文件,则:   string name = File1.PostedFile.FileName ;//获取输入的文件名字      int i= name.LastIndexOf(".") ;

asp.net文件的上传下载

Web.Config 配置文件 <?xml version="1.0"?> <configuration> <appSettings>    <add key="FileUploadPath" value="Upload/" />    <add key="FileTypeLimit" value=".zip,.rar,.dox,.ppt,.txt,.mp3&qu

通过scp实现文件的上传下载

一.什么是scp? Scp 是SSH自带的一个内置命令,是安全拷贝的意思,可以实现文件的上传和下载,传输速率快,    安全性高. 二.通过scp实现文件的上传下载 1.  从服务器下载文件到本地 (1)不指定身份下载 例:下载服务器172.25.254.116的/home/student/test/QQ/12.txt到本地/home/kiosk/ 不指定身份下载默认以当前登陆用户下载,如果当前登陆用户对下载文件没有读写权限将不能下载 (2)指定身份下载 例:以root身份下载服务器172.25

文件的上传下载

文件的上传下载包括文件的上传和文件的下载两部分,下面以项目的形式给出,项目的结构如下图所示: 项目的思路如下: 1.启动项目,输入地址:http://localhost:8080/fileUpload/upload/upload.jsp,进入文件上传界面upload.jsp. 2.文件上传的路径是UploadHandleServlet,创建临时保存文件路径(在项目的根目录的web-inf下面):                                   D:\ruanjian\tomc

JAVAWEB之文件的上传下载

文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将他们表达出来.下面是具体的步骤,大家可以跟着我一步一步的用apache的fileupload插件来完成文件的上传下载. 1.创建一个web工程,我们这里取名为fileupload 2.导入相关jar包,,数据源使用的是apache-c3p0数据源,以及上传下载插件包,goson库,以及mysql驱动

HttpClient实现文件的上传下载

1 HTTP HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源. 虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活.HttpClient 用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议. 一般的情况下我们都是使用Chrome或者

python使用ftplib模块实现FTP文件的上传下载

python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def upload(f, remote_path, local_path): fp = open(local_path, "rb") buf_size = 1024 f.storbinary("STOR {}".format(remote_path), fp, buf_size) f