asp.net 下载文件时根据MIME类型自动判断保存文件的扩展名 |
本文标签:MIME类型,自动判断 引言 用Web东风ient下载远程资源时,经常会遇到类似这样的网址: http://www.uushare.com/filedownload?user=icesee&id=2205188 http://www.guaishow.com/u/luanfujie/g9675/ 我们不知道这个Url具体代表的是一个网页,还是某种类型的文件 。 而有些Url虽然带有扩展名,但可能是错误的扩展名,常见的比如把gif文件标上了jpg扩展名 。 如果我们没法正确判断下载源的文件类型的话,就无法保存为正确的文件格式,会给后续操作及人工阅览造成困扰 。 所幸的是,WebRequest可以给出下载源的MIME信息,这让我们可以确定文件的真实格式,并以此来决定最终的存储扩展名 。(MIME是什么?) 复制代码 代码如下: 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:\Users\Public\Downloads"; //gif格式文件,正常下载 Assert.AreEqual(@"C:\Users\Public\Downloads\35ad5275ed17904d4a2d40f3dacea80b.gif", 生成下载文件存放路径(d, new Uri("/upload/2009-11/20091112231022422.gif"), "image/gif")); //url中扩展名是gif,但MIME类型实际是image/jpeg的资源 。下载后的扩展名是jpe,因为字典MimeDic里存储的对应扩展名就是jpe 。 Assert.AreEqual(@"C:\Users\Public\Downloads\35ad5275ed17904d4a2d40f3dacea80b.jpe", 生成下载文件存放路径(d, new Uri("/upload/2009-11/20091112231022422.gif"), "image/jpeg")); //一个带参数的网页url 。下载后的扩展名是dhtml,因为字典MimeDic里存储的对应扩展名就是dhtml 。 Assert.AreEqual(@"C:\Users\Public\Downloads\filedownload.dhtml", 生成下载文件存放路径(d, new Uri("http://www.uushare.com/filedownload?user=icesee&id=2205188"), "text/html")); //一个网页url,其格式为目录形式的,没有确切文件名 。 Assert.AreEqual(@"C:\Users\Public\Downloads\g9675.dhtml", 生成下载文件存放路径(d, new Uri("http://www.guaishow.com/u/luanfujie/g9675/"), "text/html")); //域名形式 Assert.AreEqual(@"C:\Users\Public\Downloads\www.g.cn.dhtml", 生成下载文件存放路径(d, new Uri("http://www.g.cn/"), "text/html")); Assert.AreEqual(@"C:\Users\Public\Downloads\g.cn.dhtml", 生成下载文件存放路径(d, 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), 0, (int)q.ContentLength); fs.Close(); b.Close(); s.Close(); return file; } 代码很简单,就不多说了,我们来完成最后的测试: 复制代码 代码如下: [TestMethod] public void 文件下载测试() { var d = @"C:\Users\Public\Downloads"; //首次下载 Assert.AreEqual(@"C:\Users\Public\Downloads\filedownload.dhtml", 下载文件(new Uri("http://www.uushare.com/filedownload?user=icesee&id=2205188"), d)); //第二次下载,遇到同名文件,自动重命名 Assert.AreEqual(@"C:\Users\Public\Downloads\filedownload(1).dhtml", 下载文件(new Uri("http://www.uushare.com/filedownload?user=icesee&id=2205188"), d)); //下载一个原本是gif类型的文件 Assert.AreEqual(@"C:\Users\Public\Downloads\2naqyw8.gif", 下载文件(new Uri("http://i38.tinypic.com/2naqyw8.jpg"), d)); } 结语 相较WebClient而言,WebRequest拥有更好的可控性,在WebClient无解的时候,就尝试让WebRequest上场吧 。 范例源代码和本文的XPS版本打包下载 http://xiazai.jb51.net/200911/yuanma/asp.net_mime_down.rar 转载http://skyd.cnblogs.com/ |