WebClient真是一个好类!不用再看WinInet那么复杂的流程和方式了(头疼),简单的两句话就可以搞定文件下载,从而达到自动下载的目的,简单易用(如果加个密还可以隐藏下载地址,顺便也推销一下我们的产品):
WebClient myWC = new WebClient();
myWC.DownloadFile(Uri, fName);
目的很简单,因为内部网站不能让别人访问,但是又需要开放下载的功能给一部分小众,所以如果有一个下载工具让用户输入文件信息然后自动下载,绝对可以减少工作量啊。最初是打算用WinInet实现,但是太复杂,后来又试过WebBrowser控件,苦于技术浅薄找不到一个理想的方法屏蔽自动下载,所以转而用WebClient,Console模式来实现,加上前期参数处理和文件信息判断,不多几行代码就可以了,很快。
主要问题解决了,次要矛盾开始转向文件处理和提示信息两个方面,因为是从公司网站上下载文件,无法预判文件大小,所以暴力的处理方式就是每隔一段时间用FileInfo对象的Length属性判断并显示;然后就是进度的问题,因为无法预知文件大小,所以即使获取到当前文件大小也不可能按照正常的进度条来处理,所以换个简单的方式,只是动态的显示下载动作在执行即可,如下面方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public static void PrintStatus() { int origRow = Console.CursorTop; int origCol = Console.CursorLeft; string s_format = "[ ]"; string s_dynamic; FileInfo fs; System.Threading.Thread.Sleep(1500); while (!isbreak) { if (File.Exists(fName)) { try { fs = new FileInfo(fName); if (fs.Length < 2048) { System.Threading.Thread.Sleep(1000); continue; } } catch (IOException ex) { System.Threading.Thread.Sleep(1000); continue; } } else { System.Threading.Thread.Sleep(1000); continue; } for (int i = 1; i <= s_format.Length - 1; i++) { try { fs = new FileInfo(fName); s_dynamic = s_format.Insert(i, "="); Console.Write(fName + " " + s_dynamic + " " + fs.Length); Console.SetCursorPosition(origCol, origRow); System.Threading.Thread.Sleep(200); } catch (IOException ex) { return; } } } Console.SetCursorPosition(origCol, origRow); } |
更好看的样式,可以参考(http://developer.51cto.com/art/200908/144390.htm),达人总是很多的。
在下载文件之前启动线程进行文件状态显示:
ThreadStart ts = new ThreadStart(PrintStatus);
Thread PrintStat = new Thread(ts);
isbreak = false;
PrintStat.Start();
有一点要注意,上面代码中判断线程是否继续执行的标志位isbreak,应该按照微软的建议申明为volatile 类型:volatile 关键字用于通知编译器,将有多个线程访问 isbreak(^^) 数据成员,因此它不应当对此成员的状态做任何优化假设;实际测试不加这个关键字,线程响应会比较慢。最后为了显示好看,在主线程中使用了一句PrintStat.Join(),效果是好的,结果是未知的