1、序言
最近项目中需要用到这个功能点,但是网上下载的时候总是出现乱码。所以趁着这个时间自己整理出了一份,以后需要的时候就直接看自己的博客就行了。已经测试过:在谷歌、火狐、IE等浏览器上都不会出现乱码问题。
2、结果展示
2.1、上传文件成功界面
2.2、下载文件成功界面
3、上传文件代码
3.1、View代码
3.2、Controller代码
[HttpPost]
public ActionResult Upload(FormCollection form)
{
if (Request.Files.Count == 0 ){
// Request.Files.Count 文件数为0上传不成功
return View();
}
var file = Request.Files[0 ];
if (file.ContentLength == 0 ){
// 文件大小大(以字节为单位)为0时,做一些操作
return View();
}
else {
// 文件大小不为0
file = Request.Files[0 ];
// 保存成自己的文件全路径,newfile就是你上传后保存的文件,
// 服务器上的UpLoadFile文件夹必须有读写权限
string target = Server.MapPath(" / " )+(" /Mock/Learning/ " );// 取得目标文件夹的路径
string filename = file.FileName;// 取得文件名字
string path = target + filename;// 获取存储的目标地址
file.SaveAs(path);}
return View();
}
4、下载文件代码
4.1、View代码
4.2、Controller代码
public ActionResult Download(string filePath, string fileName)
{
Encoding encoding;
string outputFileName = null ;
fileName = fileName.Replace(" ' " , "" );
string browser =Request.UserAgent.ToUpper();
if (browser.Contains(" MS " ) == true && browser.Contains(" IE " ) == true )
{
outputFileName = HttpUtility.UrlEncode(fileName);
encoding =Encoding.Default;
}
else if (browser.Contains(" FIREFOX " ) == true )
{
outputFileName = fileName;
encoding =Encoding.GetEncoding(" GB2312 " );
}
else
{
outputFileName = HttpUtility.UrlEncode(fileName);
encoding = Encoding.Default;
}
FileStream fs = new FileStream(filePath, FileMode.Open);
byte [] bytes = new byte [(int )fs.Length];
fs.Read(bytes, 0 , bytes.Length);
fs.Close();
Response.Charset = " UTF-8 " ;
Response.ContentType = " application/octet-stream " ;
Response.ContentEncoding = encoding;
Response.AddHeader( " Content-Disposition " , " attachment; filename= " + outputFileName);
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
return new EmptyResult();
}
在ASP.net MVC 中有几种下载文件的方法
前提: 要下载的文件必须是在服务器目录中的,至于不在web项目server目录中的文件下载我不知道,但是还挺想了解的。
第一种:最简单的超链接方法,标签的href直接指向目标文件地址,这样容易暴露地址造成盗链,这里就不说了
第二种:后台下载
在后台下载中又可以细分为几种下载方式
首先,在前台,我们需要一个标签
Home为controller,download为action。
如果需要传一些参数,可以:
在后台:
(1)返回filestream
public FileStreamResult download()
{
string fileName = " aaa.txt " ;// 客户端保存的文件名
string filePath = Server.MapPath(" ~/Document/123.txt " );// 路径
return File(new FileStream(filePath, FileMode.Open), " text/plain " ,
fileName);
}
其中:“text/plain”是文件MIME类型
(2)返回file
public FileResult download()
{
string filePath = Server.MapPath(" ~/Document/123.txt " );// 路径
return File(filePath, " text/plain " , " welcome.txt " ); //welcome.txt是客户端保存的名字
}
(3)TransmitFile方法
1 public void download()
2 {
3 string fileName = " aaa.txt " ;// 客户端保存的文件名
4 string filePath = Server.MapPath(" ~/Document/123.txt " );// 路径
5 FileInfo fileinfo = new FileInfo(filePath);
6 Response.Clear(); // 清除缓冲区流中的所有内容输出
7 Response.ClearContent(); // 清除缓冲区流中的所有内容输出
8 Response.ClearHeaders(); // 清除缓冲区流中的所有头
9 Response.Buffer = true ; // 该值指示是否缓冲输出,并在完成处理整个响应之后将其发送
10 Response.AddHeader(" Content-Disposition " , " attachment;filename= " + fileName);
11 Response.AddHeader(" Content-Length " ,fileinfo.Length.ToString());
12 Response.AddHeader(" Content-Transfer-Encoding " , " binary " );
13 Response.ContentType = " application/unknow " ; // 获取或设置输出流的 HTTP MIME 类型
14 Response.ContentEncoding = System.Text.Encoding.GetEncoding(" gb2312 " ); // 获取或设置输出流的 HTTP 字符集
15 Response.TransmitFile(filePath);
16 Response.End();
17 }
(4)Response分块下载
1 public void download()
2 {
3 string fileName = " aaa.txt " ;// 客户端保存的文件名
4 string filePath = Server.MapPath(" ~/Document/123.txt " );// 路径
5
6 System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
7 if (fileInfo.Exists == true )
8 {
9 const long ChunkSize = 102400 ;// 100K 每次读取文件,只读取100K,这样可以缓解服务器的压力
10 byte [] buffer = new byte [ChunkSize];
11
12 Response.Clear();
13 System.IO.FileStream iStream = System.IO.File.OpenRead(filePath);
14 long dataLengthToRead = iStream.Length;// 获取下载的文件总大小
15 Response.ContentType = " application/octet-stream " ;
16 Response.AddHeader(" Content-Disposition " , " attachment; filename= " + HttpUtility.UrlEncode(fileName));
17 while (dataLengthToRead > 0 && Response.IsClientConnected)
18 {
19 int lengthRead = iStream.Read(buffer, 0 , Convert.ToInt32(ChunkSize));// 读取的大小
20 Response.OutputStream.Write(buffer, 0 , lengthRead);
21 Response.Flush();
22 dataLengthToRead = dataLengthToRead - lengthRead;
23 }
24 Response.Close();
25 }
26 }
+ajax方法
要重点说说这个方法,ajax返回不了文件流,所以说用ajax调用上面任意一种后台方法都要出问题,下载不了文件。
所以,只能让后台返回所需下载文件的url地址,然后调用windows.location.href。
优点:ajax可以传好几个参数(当然以json形式),传100个都无所谓。你要是用 的方法传100得写死。。。(公司需求,至少要传100多个参数)
缺点:支持下载exe,rar,msi等类型文件。对于txt则会直接打开,慎用! 对于其他不常用的类型文件则直接报错。
所以我的建议是得到多个参数,通过数据库找到所有需要下载的文件然后压缩打包,然后返回url下载。(你要是一个一个给用户下,用户都疯了)
! 那么问题又来了,C#怎么用代码实现将本地的一些文件打包压缩到服务器目录下呢?这我不知道。
因为你只是单纯的放在目录文件夹下没有用的,我们平时在服务器某目录下添加某一个文件都是右键,添加XXX项这样,这样才能真正的将文件放在服务器中。
可是纯代码该怎么实现呢??
* 可能的解决方法:先在项目目录下放一个空的rar文件或者没什么功能的exe,msi文件,然后在后台打包完一些文件后去替换它,不知道可行不。
(1)首先清空原压缩包中的内容
(2)将文件压缩到压缩包中
(3)返回 XXX.rar
前端:
ajax:
$(" #downloadbutton " ).click(function () {
$.ajax({
type: " GET " ,
url: " /Home/download " ,
data: { id: " 1 " },
dataType: " json " ,
success: function (result) {
window.location.target = " _blank " ;
window.location.href = result;
}
})
})
后台:
public string download(int id)
{
string filePath = " Document/123.msi " ;// 路径
return filePath;
}
这里,id是没有什么作用的,后台就别用什么server.Mappath了,肯定错。直接写服务器项目文件夹/文件名 即可。
前言
这一节我们来讲讲在MVC中如何进行文件的上传,我们逐步深入,一起来看看。
Upload File(一)
我们在默认创建的项目中的Home控制器下添加如下:
public ActionResult UploadFile()
{
return View();
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
var fileName = file.FileName;
var filePath = Server.MapPath(string .Format(" ~/{0} " , " File " ));
file.SaveAs(Path.Combine(filePath, fileName));
return View();
}
在 UploadFile 视图中添加上如下:
< form action ="/Home/UploadFile" method ="post" enctype ="multipart/form-data" >
< input type ="file" name ="file" />< br />
< input type ="submit" value ="提交" />
form >
有关视图中我们就不必多说,只需明白如下两点:
(1)在后台利用HttpPostedFileBase来接收上传文件,该类为一个抽象类,但在ASP.NET Web Form却没有此类,此类的出现是为了更好的进行单元测试。
(2)在视图中文件类型的name要和后台接收文件的参数一致。
接下来我们进行演示看看结果:
上述我们简单的上传了一个Excel文件,下面我们通过强类型视图以及模型验证来强化上传。
Upload File(二)
我们创建如下BlogModel类:
public class BlogModel
{
[Display(Name = " 博客名称 " )]
[Required(ErrorMessage = " 请输入你的博客名称! " )]
public string BlogName { get ; set ; }
[Display(Name = " 博客地址 " )]
[Required(ErrorMessage = " 请输入你的博客地址! " )]
public string BlogAddress { get ; set ; }
[Display(Name = " 博客图片 " )]
[Required(ErrorMessage = " 请上传你的博客图片! " )]
[ValidateFile]
public HttpPostedFileBase BlogPhoto { get ; set ; }
}
上述未有验证文件的特性,只能自定义文件特性,如下:
public class ValidateFileAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
int MaxContentLength = 1024 * 1024 * 4 ;
string [] AllowedFileExtensions = new string [] { " .jpg " , " .gif " , " .png " , " .pdf " };
var file = value as HttpPostedFileBase;
if (file == null )
return false ;
else if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf(' . ' ))))
{
ErrorMessage = " 请上传你的博客图片类型: " + string .Join(" , " , AllowedFileExtensions);
return false ;
}
else if (file.ContentLength > MaxContentLength)
{
ErrorMessage = " 上传图片过大,不能超过4兆 : " + (MaxContentLength / 1024 ).ToString() + " MB " ;
return false ;
}
else
return true ;
}
}
我们可以任意设置上传的文件大小,我们设置为40兆,在配置文件中我们知道 maxRequestLength = 4096 默认是4兆,当然我们可以改变其默认设置。
"4.5 " executionTimeout=" 1100 " maxRequestLength=" 40960 " />
此时我们接着在控制器中修改上述上传的方法:
[HttpPost]
public ActionResult UploadFile(BlogModel bModel)
{
if (ModelState.IsValid)
{
var fileName = bModel.BlogPhoto.FileName;
var filePath = Server.MapPath(string .Format(" ~/{0} " , " File " ));
bModel.BlogPhoto.SaveAs(Path.Combine(filePath, fileName));
ModelState.Clear();
}
return View();
}
我们接下来看看效果:
咋回事,出状况了看来是我们的文件过大的原因,看了下该文件有接近45兆,而我们却设置的是40兆,于是乎继续在配置文件中去修改文件大小,但是结果还是一样。我们继续仔细看看该结果的提示,根据提示去找到配置文件下的节点再试试,我们在 syste.webServer 节点下设置为2G:
结果就好使了,查了查也有遇到类似问题的人,貌似只有给个结果,却没有给解释,为什么在 httpRuntime 中设置不行,但是有些这样设置是正确的,这是什么原因?最终找到了答案:
(1)在IIS 5和IIS 6中,默认文件上传的最大为4兆,当上传的文件大小超过4兆时,则会得到错误信息,但是我们通过如下来设置文件大小。
"2147483647 " executionTimeout=" 100000 " />
(2)在IIS 7中,默认文件上传的最大为28.6兆,当超过其默认设置大小,同样会得到错误信息,但是我们却可以通过如下来设置文件上传大小。
【类推的话,个人觉得可能是在IIS 7+以上都是通过如上述IIS 7来设置文件上传大小】
虽然我们在服务器端对其进行验证,但是我们觉得这样还是不能保险,我们继续在客户端对其上传的图片类型和大小进行验证。
(1)利用强类型视图给出视图代码:
< style type ="text/css" >
.field-validation-error {
color : red ;
}
style >
< form id ="uploadFileSub" action ="/Home/UploadFile" method ="post" enctype ="multipart/form-data" >
< fieldset >
< legend > legend >
< ul class ="lifile" >
< li >
@Html.LabelFor(m => m.BlogName) < br />
@Html.TextBoxFor(m => m.BlogName, new { maxlength = 50 })
@Html.ValidationMessageFor(m => m.BlogName)
li >
< li >
@Html.LabelFor(m => m.BlogAddress) < br />
@Html.TextBoxFor(m => m.BlogAddress, new { maxlength = 200 })
@Html.ValidationMessageFor(m => m.BlogAddress) < br />
li >
< li >
@Html.LabelFor(m => m.BlogPhoto)
@Html.TextBoxFor(m => m.BlogPhoto, new { type = "file" })
@Html.ValidationMessageFor(m => m.BlogPhoto)
< span id ="warning" style ="color:red;font-size:large;" > span >
li >
< li >
< input type ="submit" value ="提交" />
li >
ul >
fieldset >
form >
(2)利用脚本获取上传文件大小:
function GetFileSize(fileid) {
var fileSize = 0;
fileSize = $("#" + fileid)[0].files[0].size;
fileSize = fileSize / 1048576;
return fileSize;
}
(3)根据上传的路径获取文件名称:
function getNameFromPath(strFilepath) {
var objRE = new RegExp(/([^\/\\]+)$/);
var strName = objRE.exec(strFilepath);
if (strName == null ) {
return null ;
}
else {
return strName[0];
}
}
(4)当更换文件时触发Change事件对其文件类型和文件大小进行验证:
$("#BlogPhoto").change(function () {
var file = getNameFromPath($(this ).val());
if (file != null ) {
var errors = $(document).find(".field-validation-error");
$.each(errors, function (k, v) {
if ($(v).attr("data-valmsg-for") === "BlogPhoto") {
$(v).hide();
}
});
var extension = file.substr((file.lastIndexOf('.') + 1));
switch (extension) {
case 'jpg':
case 'png':
case 'gif':
case 'pdf':
fileTypeBool = false ;
break ;
default :
fileTypeBool = true ;
}
}
if (fileTypeBool) {
$( "#warning").html("只能上传扩展名为jpg,png,gif,pdf的文件!");
return false ;
}
else {
var size = GetFileSize('BlogPhoto');
if (size > 4) {
fileSizeBool = true ;
$( "#warning").html("上传文件已经超过4兆!");
} else {
fileSizeBool = false ;
}
}
});
(5)当点击提交按钮时对其进行文件进行验证:
$("#uploadFileSub").submit(function () {
$( "input[type='text']").each(function (k, v) {
if ($(v).length) {
$(v).siblings( "span").hide();
}
});
if (fileTypeBool || fileSizeBool) {
return false ;
}
});
【注意】上述对于验证不是太完整,但是基本的架子已经给出。
接下来我们来完整的演示整个过程。
上述我们一直是利用的纯HTML代码,当然也可以利用MVC的扩展方法来进行,如下(最终渲染的还是表单,本质上是一致的,就不做过多探讨了)
@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
< input type ="file" id ="file" name ="file" />
< input type ="submit" value ="提交" />
}
结语
这一节我们比较详细的讲述了在MVC中如何进行文件的上传,但是我们还有一点未曾讲到,则是利用流来将如我们上述的图片转换成字节来插入到数据库中。有关上传可以参考园友Insus.NET对此利用流来上传。
原文地址:https://www.cnblogs.com/CreateMyself/p/5414200.html