ASP.NET中怎么能同时下载多个文件或者一个文件夹?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET中怎么能同时下载多个文件或者一个文件夹?相关的知识,希望对你有一定的参考价值。
参考技术A 1一、压缩文件23usingSystem;4usingICSharpCode.SharpZipLib;5usingICSharpCode.SharpZipLib.Checksums;6usingSystem.IO;7usingICSharpCode.SharpZipLib.Zip;8usingSystem.Collections;910namespacewsUpFiles1112///<summary13///Common 的摘要说明。14///</summary15publicclassCommon1617publicCommon()1819//20//TODO: 在此处添加构造函数逻辑21//222324///<summary25///压缩文件26///</summary27///<param name="sourceFileNames"压缩文件名称集合</param28///<param name="destFileName"压缩后文件名称</param29///<param name="password"密码</param30publicstaticvoidzipFile(stringpath,stringdestFileName)3132Crc32 crc=newCrc32();33ZipOutputStream s=newZipOutputStream(File.Create(destFileName));34s.Password="";35s.SetLevel(6);//0 - store only to 9 - means best compression36//定义37System.IO.DirectoryInfo myDir=newDirectoryInfo(path);38if(myDir.Exists==true)3940System.IO.FileInfo[] myFileAry=myDir.GetFiles();4142//循环提取文件夹下每一个文件,提取信息,43foreach(FileInfo objFilesinmyFileAry)4445FileStream fs=File.OpenRead(objFiles.FullName);46byte[] buffer=newbyte[fs.Length];47fs.Read(buffer,0, buffer.Length);48ZipEntry entry=newZipEntry(objFiles.FullName);49entry.DateTime=DateTime.Now;50entry.Size=fs.Length;51fs.Close();52crc.Reset();53crc.Update(buffer);54entry.Crc=crc.Value;55s.PutNextEntry(entry);56s.Write(buffer,0, buffer.Length);5758s.Finish();59s.Close();60616263646566要对压缩文件加密时,要s.Password="aaa"; aaa为密码。6768二、解压文件6970///<summary71///解压文件72///</summary73///<param name="sourceFileName"被解压文件名称</param74///<param name="destPath"解压后文件目录</param75///<param name="password"密码</param76publicstaticvoidunzipFile(stringsourceFileName,stringdestPath,stringfileType)7778ZipInputStream s=newZipInputStream(File.OpenRead(sourceFileName));79ZipEntry theEntry;80ArrayList al=newArrayList();8182while((theEntry=s.GetNextEntry())!=null)8384stringfileName=Path.GetFileName(theEntry.Name);85if(fileName!="")8687fileName=destPath+"\\"+fileName;88if(!Directory.Exists(destPath))8990Directory.CreateDirectory(destPath);9192FileStream streamWriter=File.Create(fileName);93intsize=2048;94byte[] data=newbyte[2048];95s.Password="";96while(true)9798size=s.Read(data,0, data.Length);99if(size0)100101streamWriter.Write(data,0s.Close();113114115116注意:程序的压缩过的文件,要通过系统上的工具解压出来的路径会相当多,因其在压缩时保留了原来的绝对路径,但压缩的文件中只包含所压缩的目标文件,当用程序解压出来的文件是相对的文件路径。本回答被提问者采纳使用 FileResult 在 Asp.Net MVC 中下载任何类型的文件?
【中文标题】使用 FileResult 在 Asp.Net MVC 中下载任何类型的文件?【英文标题】:Download file of any type in Asp.Net MVC using FileResult? 【发布时间】:2011-04-05 23:54:34 【问题描述】:有人向我建议我应该使用 FileResult 来允许用户从我的 Asp.Net MVC 应用程序下载文件。但我能找到的唯一例子总是与图像文件有关(指定内容类型图像/jpeg)。
但是如果我不知道文件类型怎么办?我希望用户能够从我网站的文件区域下载几乎任何文件。
我已经阅读了一种执行此操作的方法(有关代码,请参见 previous post),它实际上工作正常,除了一件事:“另存为”对话框中出现的文件名是从文件连接起来的带下划线的路径 (folder_folder_file.ext)。此外,似乎人们认为我应该返回一个 FileResult 而不是使用我找到的这个自定义类 BinaryContentResult。
有人知道在 MVC 中进行此类下载的“正确”方式吗?
编辑: 我得到了答案(如下),但我只是想如果其他人有兴趣,我应该发布完整的工作代码:
public ActionResult Download(string filePath, string fileName)
string fullName = Path.Combine(GetBaseDir(), filePath, fileName);
byte[] fileBytes = GetFile(fullName);
return File(
fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
byte[] GetFile(string s)
System.IO.FileStream fs = System.IO.File.OpenRead(s);
byte[] data = new byte[fs.Length];
int br = fs.Read(data, 0, data.Length);
if (br != fs.Length)
throw new System.IO.IOException(s);
return data;
【问题讨论】:
你在做的是相当危险的。您几乎允许用户从您的服务器下载执行用户可以访问的任何文件。 True - 删除文件路径,并将其固定在 actionresult 的主体中会更安全一些。至少这样他们只能访问某个文件夹。 是否有任何工具可以让您找到像这个这样的潜在危险漏洞? 我发现将content-type设置为Response.ContentType = MimeMapping.GetMimeMapping(filePath);
很方便,来自***.com/a/22231074/4573839
你在客户端使用什么?
【参考方案1】:
您可以只指定通用八位字节流 MIME 类型:
public FileResult Download()
byte[] fileBytes = System.IO.File.ReadAllBytes(@"c:\folder\myfile.ext");
string fileName = "myfile.ext";
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
【讨论】:
好的,我可以试试,但是 byte[] 数组中有什么? 没关系,我想我想通了。我将文件名(完整路径)读入 FileStream,然后读入字节数组,然后它就像一个魅力!谢谢! 这会将整个文件加载到内存中,只是为了将其流出;对于大文件,这是一个猪。一个更好的解决方案是下面的解决方案,它不必先将文件加载到内存中。 因为这个答案已经快五年了,是的。如果您这样做是为了提供非常大的文件,请不要这样做。如果可能,请使用单独的静态文件服务器,这样您就不会占用应用程序线程,或者使用自 2010 年以来添加到 MVC 的许多提供文件服务的新技术之一。这仅显示了当 MIME 类型未知时要使用的正确 MIME 类型.ReadAllBytes
是多年后在一次编辑中添加的。为什么这是我第二个最赞成的答案?哦,好吧。
收到此错误:non-invocable member "File" cannot be used like a method.
【参考方案2】:
MVC 框架本身就支持这一点。 System.Web.MVC.Controller.File 控制器提供通过name/stream/array 返回文件的方法。
例如,使用文件的虚拟路径,您可以执行以下操作。
return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(virtualFilePath));
【讨论】:
【参考方案3】:如果您使用的是 .NET Framework 4.5,那么您可以使用 MimeMapping.GetMimeMapping(string FileName) 来获取文件的 MIME-Type。这就是我在行动中使用它的方式。
return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName);
【讨论】:
获取 Mime 映射很好,但在运行时确定文件类型不是一个繁重的过程吗? @MohammedNoureldin 它不是在“计算”它,有一个基于文件扩展名或类似东西的简单映射表。服务器对所有静态文件执行此操作,并不慢。【参考方案4】:Phil Haack 有一个很好的article,他在其中创建了一个自定义文件下载操作结果类。只需要指定文件的虚拟路径和保存的名称即可。
我用过一次,这是我的代码。
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Download(int fileID)
Data.LinqToSql.File file = _fileService.GetByID(fileID);
return new DownloadResult VirtualPath = GetVirtualPath(file.Path),
FileDownloadName = file.Name ;
在我的示例中,我存储了文件的物理路径,所以我使用了这个帮助方法——我在某个我不记得的地方找到了——将它转换为虚拟路径
private string GetVirtualPath(string physicalPath)
string rootpath = Server.MapPath("~/");
physicalPath = physicalPath.Replace(rootpath, "");
physicalPath = physicalPath.Replace("\\", "/");
return "~/" + physicalPath;
这是摘自 Phill Haack 文章的完整课程
public class DownloadResult : ActionResult
public DownloadResult()
public DownloadResult(string virtualPath)
this.VirtualPath = virtualPath;
public string VirtualPath
get;
set;
public string FileDownloadName
get;
set;
public override void ExecuteResult(ControllerContext context)
if (!String.IsNullOrEmpty(FileDownloadName))
context.HttpContext.Response.AddHeader("content-disposition",
"attachment; filename=" + this.FileDownloadName)
string filePath = context.HttpContext.Server.MapPath(this.VirtualPath);
context.HttpContext.Response.TransmitFile(filePath);
【讨论】:
对,是的,我也看到了那篇文章,但它似乎和我使用的文章做的一样(参见我之前帖子的参考),他在顶部说自己不再需要解决方法的页面,因为:“新更新:不再需要此自定义 ActionResult,因为 ASP.NET MVC 现在在框中包含一个。”但不幸的是,他没有说明如何使用它。 @ManafAbuRous,如果您仔细阅读代码,您会发现它实际上将虚拟路径转换为物理路径 (Server.MapPath(this.VirtualPath)
),因此直接使用它而不进行更改有点幼稚。您应该生成一个接受PhysicalPath
的替代方案,因为这是最终需要的并且是您要存储的。这会更安全,因为您假设物理路径和相对路径是相同的(不包括根)。数据文件通常存储的是App_Data。这不能作为相对路径访问。
GetVirtualPath 很棒....非常有用。谢谢!【参考方案5】:
感谢伊恩·亨利!
如果您需要从 MS SQL Server 获取文件,这就是解决方案。
public FileResult DownloadDocument(string id)
if (!string.IsNullOrEmpty(id))
try
var fileId = Guid.Parse(id);
var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId);
if (myFile != null)
byte[] fileBytes = myFile.FileData;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName);
catch
return null;
其中 AppModel 是 EntityFramework
模型,MyFiles 在您的数据库中显示 table。
FileData 是 MyFiles 表中的 varbinary(MAX)
。
【讨论】:
【参考方案6】:它很简单,只需在 directoryPath 中提供您的物理路径和文件名
public FilePathResult GetFileFromDisk(string fileName)
return File(directoryPath, "multipart/form-data", fileName);
【讨论】:
客户端呢,调用这个方法呢?假设你想显示另存为对话框?【参考方案7】: public ActionResult Download()
var document = //Obtain document from database context
var cd = new System.Net.Mime.ContentDisposition
FileName = document.FileName,
Inline = false,
;
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
【讨论】:
【参考方案8】:if (string.IsNullOrWhiteSpace(fileName)) return Content("文件名不存在");
var path = Path.Combine(your path, your filename);
var stream = new FileStream(path, FileMode.Open);
return File(stream, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
【讨论】:
【参考方案9】:GetFile 应该关闭文件(或在使用中打开它)。然后你可以在转换为字节后删除文件——下载将在那个字节缓冲区上完成。
byte[] GetFile(string s)
byte[] data;
using (System.IO.FileStream fs = System.IO.File.OpenRead(s))
data = new byte[fs.Length];
int br = fs.Read(data, 0, data.Length);
if (br != fs.Length)
throw new System.IO.IOException(s);
return data;
所以在你的下载方法中...
byte[] fileBytes = GetFile(file);
// delete the file after conversion to bytes
System.IO.File.Delete(file);
// have the file download dialog only display the base name of the file return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(file));
【讨论】:
请永远不要像这样将整个文件加载到内存中投入生产以上是关于ASP.NET中怎么能同时下载多个文件或者一个文件夹?的主要内容,如果未能解决你的问题,请参考以下文章
asp.net 点击一下文件名或者一个下载按钮,将文件下载下来怎么做啊???
ASP.NET中怎么实现多文件同时上传?要求点浏览的时候可以一次性多选文件