用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映射字典 
我们首先需要做的工作就是建立一个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:\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/
MIME类型,自动判断
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
 - 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
 - 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
 - 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
 - 群星《2024好听新歌42》AI调整音效【WAV分轨】
 - 王思雨-《思念陪着鸿雁飞》WAV
 - 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
 - 李健《无时无刻》[WAV+CUE][590M]
 - 陈奕迅《酝酿》[WAV分轨][502M]
 - 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
 - 群星《吉他王(黑胶CD)》[WAV+CUE]
 - 齐秦《穿乐(穿越)》[WAV+CUE]
 - 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
 - 邝美云《邝美云精装歌集》[DSF][1.6G]
 - 吕方《爱一回伤一回》[WAV+CUE][454M]