ASP.NET MVC 向浏览器发送文件以提供文件下载功能

     撑到大三了,结果发现周围的同学更加堕落了,尤其是某些人,表面上看起来很认真,实际上三天打鱼,两天晒网,结果一事无成,却还要抱怨学校教育失败。

     为了吸取他们的教训,就算是一个小小的编码问题,我也要努力解决。因为学习的机会一向都在,只是自己有没有去努力而已。

     之前做个班级站点的课程设计,用一天半的时间做完虽然各方面不咋样,但麻雀虽小,五脏俱在,功能流程还是挺完整的。

     就算是一个小小的课程设计,在这短暂的时间内,也遇到了不少问题,有大有小。

     先说文件下载这块。

     文件下载一般都是需要一个文件选择对话框来选择存放文件的地方。我们可以自己做一个,但简单的方面就是利用浏览器的现成功能。

     所有的浏览器都包括文件下载功能,但文件选择对话框却不是每个浏览器都有提供。这里我只选择我常用的两个浏览器:谷歌浏览器和搜狗浏览器。

     先来一个小例子:

public ActionResult Index()
{
     var path = Server.MapPath("~/frog.jpg.jpg");
     return File(path, "iamge/jpeg");
}

     这里是下载工程根目录下的frog.jpg.jpg。
     代码非常简短,只有两行,但效果却不差:

      

      这是搜狗浏览器上的效果,如果是谷歌浏览器,则是直接下载下来,但是文件并不是我们的文件名,甚至格式也不一样,就是一个奇怪的名为"下载"的文件。

      首先是解释上面两行代码的原理:

      Server.MapPath()的参数是一个虚拟路径的,它的原理是根据提供的虚拟路径返回一个虚拟路径对应的物理路径,而且参数路径必须是虚拟路径。我们服务器上传的文件都是放在服务器的一个路径下,这个路径是物理路径,但是打开文件的URL却是虚拟路径,这样的好处就像是相对路径和绝对路径的对比,想想如果我们将文件的额存放地点放在另一个地方,如果URL为物理路径,那么就会找不到该文件。

      path现在是frog.jpg.jpg的物理路径,然后我们要将该文件发送给浏览器,则需要利用FilePathResult的File(),指定发送文件的物理路径和格式就可以了。

      值得注意的是,如果是在搜狗中,指定格式是application/x-zip-compressed(zip的MIME格式)或者application/octet-stream(rar的MIME格式),在网页上看到的将会是乱码,但如果是谷歌,依然是上面那样的情况,但是用压缩文件软件打开,就会发现里面就是我们要的文件,它确实是被下载下来了。

      由于谷歌浏览器的行为与我们想要的效果差了太远了,所以下面就不再讨论谷歌浏览器的行为。

      我用word文档,Excel表格和txt文档格式的文件分别发送给浏览器,结果只有txt文档的文件中的内容能够正常显示在网页中,其他都是乱码,可见,网页能够直接打开的文件格式是有限的,至少需要第三方软件打开的文件是无法打开的。

      上面这些都不是重点,只是我的一点好奇心而已。现在我们进入重点,就是让浏览器提供下载对话框。

      要实现这样的功能,上面的代码是不行的,至少我这边是不行的,要用下面的代码: 

var path = Server.MapPath("~/1.txt");
var name = Path.GetFileName(path);
return File(path, "application/zip-x-compressed", name);

      然后浏览器的运行效果如:

  

     这就是我们想要的结果。

     我们增加了一行代码,就是使用Path.GetFileName()来获取指定物理路径的文件的文件名和扩展名,然后再在File()中增加一个新的参数,该参数就是我们要下载的文件的文件名和扩展名。

      但可怕的是,上面代码中File的格式可以随便指定,甚至可以直接为"1"(只要不是null以及""),都会提供上面的下载对话框!!这告诉我们,该下载对话框需要的并不是文件的正确格式,它需要的仅仅只是需要下载的文件的文件名(这个文件名并一定要是正确的文件名,我们可以指定新的名字,反正它就只要将该物理路径下的那个文件下载下来就行)以及该文件的物理路径。

   必须注意的是,如果文件名包含有中文,那么它就会显示这样的效果:

        如果想要显示正确的中文文件名,我们可以这样做:

return File(path, "1", Url.Encode(name));

        效果就会这样:

       

   要实现上面的效果,我们还可以这样做:
byte[] data = Encoding.UTF8.GetBytes("~/中国.txt");
return File(data, "1", Url.Encode("中国.txt"));

      这里我们是直接将"~/中国.txt"变为byte[]数组然后发给浏览器,保存在中国.txt中,打开就是"~/中国.txt"。这种方式属于FileContentResult。

      大概的内容就是上面这样,当然我们可以自定义,毕竟像是谷歌浏览器根本就不提供下载对话框的情况下,更加需要我们自定义下载对话框,但这里不讲,先是这样,以后再继续补充。

原文地址:https://www.cnblogs.com/wenjiang/p/3149038.html