最近项目中需要用到这个功能点,但是网上下载的时候总是出现乱码。所以趁着这个时间自己整理出了一份,以后需要的时候就直接看自己的博客就行了。已经测试过:在谷歌、火狐、IE等浏览器上都不会出现乱码问题。
2、结果展示
2.1、上传文件成功界面
2.2、下载文件成功界面
3、上传文件代码
3.1、View代码
@*
new
{ enctype =
"
multipart/form-data
"
}比不可少,否则上传文件不会成功 *
@
@using (Html.BeginForm(
"
Upload
"
,
"
UploadFile
"
, FormMethod.Post,
new
{ enctype =
"
multipart/form-data
"
}))
<text>选择上传文件:</text><input name=
"
file
"
type=
"
file
"
id=
"
file
"
/>
<input type=
"
submit
"
name=
"
Upload
"
value=
"
Upload
"
/>
//
保存成自己的文件全路径,newfile就是你上传后保存的文件,
//
服务器上的UpLoadFile文件夹必须有读写权限
string
target = Server.MapPath(
"
/
"
)+(
"
/Mock/Learning/
"
);
//
取得目标文件夹的路径
string
filename = file.FileName;
//
取得文件名字
string
path = target + filename;
//
获取存储的目标地址
file.SaveAs(path);}
return
View();
4.1、View代码
<a href="/DownloadFile/Download?filePath=@ViewBag.Value&fileName='小王子.pdf'">下载</a>
4.2、Controller代码
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
"
);
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();
前提:
要下载的文件必须是在服务器目录中的,至于不在web项目server目录中的文件下载我不知道,但是还挺想了解的。
第一种:最简单的超链接方法,<a>标签的href直接指向目标文件地址,这样容易暴露地址造成盗链,这里就不说了
第二种:后台下载
在后台下载中又可以细分为几种下载方式
首先,在前台,我们需要一个<a>标签
<a href="~/Home/download">Click to get file</a>
Home为controller,download为action。
如果需要传一些参数,可以:
<a href="~/Home/download?id=1">Click to get file</a>
(1)返回filestream
string
fileName =
"
aaa.txt
"
;
//
客户端保存的文件名
string
filePath = Server.MapPath(
"
~/Document/123.txt
"
);
//
路径
return
File(
new
FileStream(filePath, FileMode.Open),
"
text/plain
"
,
fileName);
public FileResult download()
string filePath = Server.MapPath("~/Document/123.txt");//路径
return File(filePath, "text/plain", "welcome.txt"); //welcome.txt是客户端保存的名字
(3)TransmitFile方法
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();
3 string fileName = "aaa.txt";//客户端保存的文件名
4 string filePath = Server.MapPath("~/Document/123.txt");//路径
6 System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath);
7 if (fileInfo.Exists == true)
9 const long ChunkSize = 102400;//100K 每次读取文件,只读取100K,这样可以缓解服务器的压力
10 byte[] buffer = new byte[ChunkSize];
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 }
<input>+ajax方法
要重点说说这个方法,ajax返回不了文件流,所以说用ajax调用上面任意一种后台方法都要出问题,下载不了文件。
所以,只能让后台返回所需下载文件的url地址,然后调用windows.location.href。
优点:ajax可以传好几个参数(当然以json形式),传100个都无所谓。你要是用<a href="网址?参数=值"></a>的方法传100得写死。。。(公司需求,至少要传100多个参数)
缺点:支持下载exe,rar,msi等类型文件。对于txt则会直接打开,慎用!对于其他不常用的类型文件则直接报错。
所以我的建议是得到多个参数,通过数据库找到所有需要下载的文件然后压缩打包,然后返回url下载。(你要是一个一个给用户下,用户都疯了)
!那么问题又来了,C#怎么用代码实现将本地的一些文件打包压缩到服务器目录下呢?这我不知道。
因为你只是单纯的放在目录文件夹下没有用的,我们平时在服务器某目录下添加某一个文件都是右键,添加XXX项这样,这样才能真正的将文件放在服务器中。
可是纯代码该怎么实现呢??
* 可能的解决方法:先在项目目录下放一个空的rar文件或者没什么功能的exe,msi文件,然后在后台打包完一些文件后去替换它,不知道可行不。
(1)首先清空原压缩包中的内容
(2)将文件压缩到压缩包中
(3)返回 XXX.rar
<input type="button" id="downloadbutton"/>
ajax:
success: function (result) {
window.location.target = "_blank";
window.location.href = result;
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类:
[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;
return true;
我们可以任意设置上传的文件大小,我们设置为40兆,在配置文件中我们知道 maxRequestLength = 4096 默认是4兆,当然我们可以改变其默认设置。
<httpRuntime targetFramework="4.5" executionTimeout="1100" maxRequestLength="40960" />
此时我们接着在控制器中修改上述上传的方法:
var fileName = bModel.BlogPhoto.FileName;
var filePath = Server.MapPath(string.Format("~/{0}", "File"));
bModel.BlogPhoto.SaveAs(Path.Combine(filePath, fileName));
ModelState.Clear();
return View();
结果就好使了,查了查也有遇到类似问题的人,貌似只有给个结果,却没有给解释,为什么在 httpRuntime 中设置不行,但是有些这样设置是正确的,这是什么原因?最终找到了答案:
(1)在IIS 5和IIS 6中,默认文件上传的最大为4兆,当上传的文件大小超过4兆时,则会得到错误信息,但是我们通过如下来设置文件大小。
<system.web>
<httpRuntime maxRequestLength="2147483647" executionTimeout="100000" />
</system.web>
(2)在IIS 7中,默认文件上传的最大为28.6兆,当超过其默认设置大小,同样会得到错误信息,但是我们却可以通过如下来设置文件上传大小。
【类推的话,个人觉得可能是在IIS 7+以上都是通过如上述IIS 7来设置文件上传大小】
虽然我们在服务器端对其进行验证,但是我们觉得这样还是不能保险,我们继续在客户端对其上传的图片类型和大小进行验证。
(1)利用强类型视图给出视图代码:
</style>
<form id="uploadFileSub" action="/Home/UploadFile" method="post" enctype="multipart/form-data">
<fieldset>
<legend></legend>
<ul class="lifile">
@Html.LabelFor(m => m.BlogName)<br />
@Html.TextBoxFor(m => m.BlogName, new { maxlength = 50 })
@Html.ValidationMessageFor(m => m.BlogName)
@Html.LabelFor(m => m.BlogAddress)<br />
@Html.TextBoxFor(m => m.BlogAddress, new { maxlength = 200 })
@Html.ValidationMessageFor(m => m.BlogAddress)<br />
@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>
<input type="submit" value="提交" />
</fieldset>
</form>
function GetFileSize(fileid) {
var fileSize = 0;
fileSize = $("#" + fileid)[0].files[0].size;
fileSize = fileSize / 1048576;
return fileSize;
function getNameFromPath(strFilepath) {
var objRE = new RegExp(/([^\/\\]+)$/);
var strName = objRE.exec(strFilepath);
if (strName == null) {
return null;
else {
return strName[0];
$("#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;
$("#uploadFileSub").submit(function () {
$("input[type='text']").each(function (k, v) {
if ($(v).length) {
$(v).siblings("span").hide();
if (fileTypeBool || fileSizeBool) {
return false;
@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
初次认识asp.net mvc时,以为所有文件都需要走一遍路由,然后才能在客户端显示,所以我首先介绍这一种方式比如说:我们在服务器上有图片: ~/resource/image/5.jpg我们就需要在控制器下新写:(旨在当浏览器发出请求时,服务器内存读取图片文件,以图片流的方式传给浏览器)public ActionResult GetImg(){string strPath = Server.Map...
解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹/// 被压缩的文件名称(包含文件路径)/// 压缩后的文件名称(包含文件路径)
网上有各种各样的说法和办法,但都不好用,或没有说到关键的地方。
还有的建议传字符串后台格式化或解析,也有专门写一个切面程序修改mvc自带的格式化方法的,等等,都不是想要的东东。
我需要的是一个简简单单,不做任何改动就能实现的方法。
今天遇到这个问题,反复调试了好多次,终于找到了最简单的方法,什么都...
本例旨在说明我的一种Controller接收ajax提交(POST)过来的json对象或数组信息的方式,感觉应该有更好的方式,欢迎提出宝贵意见。JSON.stringify(jsonObj)不支持IE8以下浏览器 前端页面代码如下:
在网站开发中我们经常需要用到表单,那么,在前台页面的表单中提交到后台控制器后,后台控制器就要接收表单提交过来的数据,然后实现新增功能
我们可以先写一个HTML的前端页面的表单来作为前台页面。
大致是要新建一个MVC项目,然后添加一个控制器,;在控制器的默认方法index中,
代码如下,新增功能的实现:
先看控制器的代码
在点击Create.aspx页面中的 Create 按钮时执行上面这段代码,如果新增信息成功则打开Index.aspx页面,如果失败则打开Create.aspx页面进行重新输入
[HttpPost("Upload")]
[RequestSizeLimit(1024 * 10240)]
public string Upload(List<IFormFile> files)
NLogHelper.Info("====SavePicture===");
var url="http://xxxxxx.com/abc.pdf";
System.Net.WebRequest myRequest = System.Net.WebRequest.Create(url);
System.Net.WebResponse myResponse = myRequest.GetResponse();
var file=myResponse.GetResponseStream();.
我已经在运行.net MVC应用程序的Web服务器上设置了到另一台用于存储上载文件的服务器的网络路径。为了允许通过应用程序将文件上传到网络路径,我修改了IIS中的应用程序池,以便该应用程序有权上传到它。这一切都很好。为了使应用程序在加载页面时能够读取文件,我在IIS中创建了一个虚拟目录,该目录现在作为IIS中该站点的文件系统的一部分出现。然后,如何在我的应用程序中访问并为此位置生成路径,以便可以将...
<form action='@Url.Action("Upload", "File")' method="post" enctype="multipart/form-data">
<input type="file" name="file" />
asp.net里提供了多种方式,从服务器端向客户端写文件流,实现客户端下载文件。这种技术在做防下载系统时比较有用处。其中WriteFilet和BinaryWrite出现得比较早,对文件流的输出可以启动作用,但由于都是将整个文件读到内存后再往客户端写,因此会占用大量的内存资源,特别是要下载的文件比较大时,影响asp.net应用的稳定运行。
今天因为工作需要,写一个Excel上传下载的.Net MVC工程的Demo。因为自己是个新手,再编写的过程中百度无数次,遇到很多低级错误。最终完成后,发现在.Net MVC中实现文件上传和下载都非常简单。
首先,在VS中创建一个.Net MVC工程,工程中默认带有了一套MVC的样例代码。因为只是写Demo,我就直接在这个基础上进行了小改动以实现自己需要的效果。