asp.net 下载文件时根据MIME类型自动判断保存文件的扩展名
发布时间:2020-12-15 20:44:34 所属栏目:asp.Net 来源:网络整理
导读:引言 用WebClient下载远程资源时,经常会遇到类似这样的网址: http://www.uushare.com/filedownload?user=iceseenbsp; 这个通过正则表达式转换而来的代码量非常大。 需注意的是,其中有很多MIME类型相同但扩展名不同的数据,我们在添加到字典时就将多余的不
引言
用WebClient下载远程资源时,经常会遇到类似这样的网址: http://www.uushare.com/filedownload?user=icesee&id=2205188 http://www.guaishow.com/u/luanfujie/g9675/ 我们不知道这个Url具体代表的是一个网页,还是某种类型的文件。 而有些Url虽然带有扩展名,但可能是错误的扩展名,常见的比如把gif文件标上了jpg扩展名。 如果我们没法正确判断下载源的文件类型的话,就无法保存为正确的文件格式,会给后续操作及人工阅览造成困扰。 所幸的是,WebRequest可以给出下载源的MIME信息,这让我们可以确定文件的真实格式,并以此来决定最终的存储扩展名。(MIME是什么?) 这个通过正则表达式转换而来的代码量非常大。 需注意的是,其中有很多MIME类型相同但扩展名不同的数据,我们在添加到字典时就将多余的不必要记录忽略了,比如高亮处的那三条都是audio/x-aiff类型,那么后两个扩展名都不会添加到字典中,也不会在后续的操作中被使用。 如果你觉得有些类型添加的对应扩展名不是最常见的对应类型的话,就得手动调整代码了。(下文中就出现了这种情况,如text/html对应的是dhtml扩展名,image/jpeg对应的是jpe扩展名) 字典构建完毕之后,就可以通过这样一个方法来获取MIME类型所对应的扩展名了: string 获取对应扩展名(string ContentType) { foreach (var f in MimeDic.Keys) { if (ContentType.ToLower().IndexOf(f) >= 0) return MimeDic[f]; } return null; } 这里之所以使用IndexOf方法判断,是因为传入的ContentType中可能还包含其他信息,比如编码格式。 题外话:看到网上曾有人抱怨说WebClient下载网页时容易产生乱码,而且又不好读取网页的编码格式,其实WebRequest的ContentType中就包含MIME和编码格式信息: 生成下载文件路径 现在有了上面的方法,我们就可以通过MIME类型确定文件的扩展名了。 现在我们将书写一个用于生成下载文件路径的方法,其功能为: 分析文件的源Url,将其文件名部分作为下载文件的文件名。 如果其Url中不含文件名部分(域名或目录形式),则以其目录名为下载文件的文件名。 根据传入的MIME类型自动确定并替换Url中的原始扩展名(如果有的话),以用作下载文件的文件名。 判断传入的存储目录中是否已存在与下载文件名相同的文件,存在的话就进行重命名,直到没有同名文件为止。 功能有点多了,不适合做范例,不过还是很实用的,所以这里就顺道分享出来。 其代码为: 复制代码 代码如下: string 生成下载文件存放路径(string 存放目录,Uri Uri,string ContentType) { var ex = 获取对应扩展名(ContentType); string up = null; string upne = null; if (Uri.LocalPath == "/") { //处理Url是域名的情况 up = upne = Uri.Host; } else { if (Uri.LocalPath.EndsWith("/")) { //处理Url是目录的情况 up = Uri.LocalPath.Substring(0,Uri.LocalPath.Length - 1); upne = Path.GetFileName(up); } else { //处理常规Url up = Uri.LocalPath; upne = Path.GetFileNameWithoutExtension(up); } } var name = string.IsNullOrEmpty(ex) ? Path.GetFileName(up) : upne + "." + ex; var fn = Path.Combine(存放目录,name); var x = 1; while (File.Exists(fn)) { fn = Path.Combine(存放目录,Path.GetFileNameWithoutExtension(name) + "(" + x++ + ")" + Path.GetExtension(name)); } return fn; } 为了验证其效果,我们通过一个单元测试进行评测: 复制代码 代码如下: [TestMethod] public void 文件名生成测试() { var d = @"C:UsersPublicDownloads"; //gif格式文件,正常下载 Assert.AreEqual(@"C:UsersPublicDownloads35ad5275ed17904d4a2d40f3dacea80b.gif",生成下载文件存放路径(d,new Uri("/upload/2009-11/20091112231022422.gif"),"image/gif")); //url中扩展名是gif,但MIME类型实际是image/jpeg的资源。下载后的扩展名是jpe,因为字典MimeDic里存储的对应扩展名就是jpe。 Assert.AreEqual(@"C:UsersPublicDownloads35ad5275ed17904d4a2d40f3dacea80b.jpe","image/jpeg")); //一个带参数的网页url。下载后的扩展名是dhtml,因为字典MimeDic里存储的对应扩展名就是dhtml。 Assert.AreEqual(@"C:UsersPublicDownloadsfiledownload.dhtml",new Uri("http://www.uushare.com/filedownload?user=icesee&id=2205188"),"text/html")); //一个网页url,其格式为目录形式的,没有确切文件名。 Assert.AreEqual(@"C:UsersPublicDownloadsg9675.dhtml",new Uri("http://www.guaishow.com/u/luanfujie/g9675/"),"text/html")); //域名形式 Assert.AreEqual(@"C:UsersPublicDownloadswww.g.cn.dhtml",new Uri("http://www.g.cn/"),"text/html")); Assert.AreEqual(@"C:UsersPublicDownloadsg.cn.dhtml",new Uri("http://g.cn"),"text/html")); } 文件下载 万事俱备,只欠东风了,让我们来完成下载方法: 复制代码 代码如下: /// <summary> /// 下载文件到指定目录,并返回下载后存放的文件路径 /// </summary> /// <param name="Uri">网址</param> /// <param name="存放目录">存放目录,如果该目录中已存在与待下载文件同名的文件,那么将自动重命名</param> /// <returns>下载文件存放的文件路径</returns> public string 下载文件(Uri Uri,string 存放目录) { var q = WebRequest.Create(Uri).GetResponse(); var s = q.GetResponseStream(); var b = new BinaryReader(s); var file = 生成下载文件存放路径(存放目录,Uri,q.ContentType); FileStream fs = new FileStream(file,FileMode.Create,FileAccess.Write); fs.Write(b.ReadBytes((int)q.ContentLength),(int)q.ContentLength); fs.Close(); b.Close(); s.Close(); return file; } 代码很简单,就不多说了,我们来完成最后的测试: 复制代码 代码如下: [TestMethod] public void 文件下载测试() { var d = @"C:UsersPublicDownloads"; //首次下载 Assert.AreEqual(@"C:UsersPublicDownloadsfiledownload.dhtml",下载文件(new Uri("http://www.uushare.com/filedownload?user=icesee&id=2205188"),d)); //第二次下载,遇到同名文件,自动重命名 Assert.AreEqual(@"C:UsersPublicDownloadsfiledownload(1).dhtml",d)); //下载一个原本是gif类型的文件 Assert.AreEqual(@"C:UsersPublicDownloads2naqyw8.gif",下载文件(new Uri("http://i38.tinypic.com/2naqyw8.jpg"),d)); } 结语 相较WebClient而言,WebRequest拥有更好的可控性,在WebClient无解的时候,就尝试让WebRequest上场吧。 范例源代码和本文的XPS版本打包下载 http://xiazai.aspzz.cn/200911/yuanma/asp.net_mime_down.rar 转载http://skyd.cnblogs.com/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- 经典ASP页面的性能测试?
- asp.net – OutputCache.VaryByHeader没有在响应中生成Vary
- asp.net-core – ASP .NET Core默认语言总是英文
- asp.net – 如何使用web.config文件保护页面?
- asp.net-mvc – 说ASP .NET MVC应用程序是HTTPModule是正确
- 加载ASP.Net MVC JSONResult jQuery DataTables
- asp.net-mvc-routing – 如何检查给定路径是否存在路由(ASP
- asp.net – IIS动态压缩失败
- asp.net – 何时使用HttpApplicationState而不是Web.Cachin
- asp.net-mvc – 无法在MVC 3中禁用“……有潜在危险的Reque
推荐文章
站长推荐
- asp.net-mvc – html属性中的Razor语法
- asp.net-mvc – Html.Hidden字段未设置
- 如何在IIS 7上的经典ASP中启用大型文件的上传?
- ASP.NET MVC如何实现自定义验证(服务端验证+客户
- asp.net-mvc-3 – 在脚手架视图MVC3中进行分页
- 提高ASP.NETWeb应用性能的24种方法和技巧
- 在ASP.NET MVC中使用“RadioButtonList”和“Che
- asp.net – 在IE7 / IE8兼容模式下,ModalPopupEx
- ASP.NET Azure中的Trace.WriteLine
- 在asp.net中使用绑定表达式时,如何连接文本?
热点阅读