PowerShell实现文件下载(类wget)
对Linux熟悉的读者可能会对Linux通过wget下载文件有印象,这个工具功能很强大,在.NET环境下提到下载文件大多数人熟悉的是通过System.Net.WebClient进行下载,这个程序集能实现下载的功能,但是有缺陷,如果碰上类似于.../scripts/?dl=417这类的下载链接将无法正确识别文件名,下载的文件通常会被命名为dl=417这样古怪的名字,其实对应的文件名是在访问这个链接返回结果的HTTP头中包含的。事实上微软也提供了避免这些缺陷的程序集System.Net.HttpWebRequest 和 HttpWebResponse,本文将会使用这两个程序集来实现PowerShell版wget的功能。
代码不怎么复杂,基本上就是创建HttpWebRequest对象,设定UserAgent和CookieContainer以免在遇到设置防盗链的服务器出现无法下载的情况。然后通过HttpWebRequest对象的GetResponse()方法从http头中获取目标文件的大小以及文件名,以便能在下载到文件时提示当前下载进度,在下载完文件后,列出当前目录下对应的文件。代码不复杂,有任何疑问的读者可以留言给我,进行交流,下面上代码:
=====文件名:Get-WebFile.ps1=====
function Get-WebFile {
<# Author:fuhj(powershell#live.cn ,http://fuhaijun.com)
Downloads a file or page from the web
.Example
Get-WebFile http://mirrors.cnnic.cn/apache/couchdb/binary/win/1.4.0/setup-couchdb-1.4.0_R16B01.exe
Downloads the latest version of this file to the current directory
#> [CmdletBinding(DefaultParameterSetName="NoCredentials")]
param(
# The URL of the file/page to download
[Parameter(Mandatory=$true,Position=0)]
[System.Uri][Alias("Url")]$Uri # = (Read-Host "The URL to download")
,
# A Path to save the downloaded content.
[string]$FileName
,
# Leave the file unblocked instead of blocked
[Switch]$Unblocked
,
# Rather than saving the downloaded content to a file, output it.
# This is for text documents like web pages and rss feeds, and allows you to avoid temporarily caching the text in a file.
[switch]$Passthru
,
# Supresses the Write-Progress during download
[switch]$Quiet
,
# The name of a variable to store the session (cookies) in
[String]$SessionVariableName
,
# Text to include at the front of the UserAgent string
[string]$UserAgent = "PowerShellWget/$(1.0)"
) Write-Verbose "Downloading '$Uri'"
$EAP,$ErrorActionPreference = $ErrorActionPreference, "Stop"
$request = [System.Net.HttpWebRequest]::Create($Uri);
$ErrorActionPreference = $EAP
$request.UserAgent = $(
"{0} (PowerShell {1}; .NET CLR {2}; {3}; http://fuhaijun.com)" -f $UserAgent,
$(if($Host.Version){$Host.Version}else{"1.0"}),
[Environment]::Version,
[Environment]::OSVersion.ToString().Replace("Microsoft Windows ", "Win")
) $Cookies = New-Object System.Net.CookieContainer
if($SessionVariableName) {
$Cookies = Get-Variable $SessionVariableName -Scope 1
}
$request.CookieContainer = $Cookies
if($SessionVariableName) {
Set-Variable $SessionVariableName -Scope 1 -Value $Cookies
} try {
$res = $request.GetResponse();
} catch [System.Net.WebException] {
Write-Error $_.Exception -Category ResourceUnavailable
return
} catch {
Write-Error $_.Exception -Category NotImplemented
return
} if((Test-Path variable:res) -and $res.StatusCode -eq 200) {
if($fileName -and !(Split-Path $fileName)) {
$fileName = Join-Path (Convert-Path (Get-Location -PSProvider "FileSystem")) $fileName
}
elseif((!$Passthru -and !$fileName) -or ($fileName -and (Test-Path -PathType "Container" $fileName)))
{
[string]$fileName = ([regex]'(?i)filename=(.*)$').Match( $res.Headers["Content-Disposition"] ).Groups[1].Value
$fileName = $fileName.trim("\/""'") $ofs = ""
$fileName = [Regex]::Replace($fileName, "[$([Regex]::Escape(""$([System.IO.Path]::GetInvalidPathChars())$([IO.Path]::AltDirectorySeparatorChar)$([IO.Path]::DirectorySeparatorChar)""))]", "_")
$ofs = " " if(!$fileName) {
$fileName = $res.ResponseUri.Segments[-1]
$fileName = $fileName.trim("\/")
if(!$fileName) {
$fileName = Read-Host "Please provide a file name"
}
$fileName = $fileName.trim("\/")
if(!([IO.FileInfo]$fileName).Extension) {
$fileName = $fileName + "." + $res.ContentType.Split(";")[0].Split("/")[1]
}
}
$fileName = Join-Path (Convert-Path (Get-Location -PSProvider "FileSystem")) $fileName
}
if($Passthru) {
$encoding = [System.Text.Encoding]::GetEncoding( $res.CharacterSet )
[string]$output = ""
} [int]$goal = $res.ContentLength
$reader = $res.GetResponseStream()
if($fileName) {
try {
$writer = new-object System.IO.FileStream $fileName, "Create"
} catch {
Write-Error $_.Exception -Category WriteError
return
}
}
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$count = 0
do
{
$count = $reader.Read($buffer, 0, $buffer.Length);
if($fileName) {
$writer.Write($buffer, 0, $count);
}
if($Passthru){
$output += $encoding.GetString($buffer,0,$count)
} elseif(!$quiet) {
$total += $count
if($goal -gt 0) {
Write-Progress "Downloading $Uri" "Saving $total of $goal" -id 0 -percentComplete (($total/$goal)*100)
} else {
Write-Progress "Downloading $Uri" "Saving $total bytes..." -id 0
}
}
} while ($count -gt 0) $reader.Close()
if($fileName) {
$writer.Flush()
$writer.Close()
}
if($Passthru){
$output
}
}
if(Test-Path variable:res) { $res.Close(); }
if($fileName) {
ls $fileName
}
}
调用方法,如下:
Get-WebFile http://mirrors.cnnic.cn/apache/couchdb/binary/win/1.4.0/setup-couchdb-1.4.0_R16B01.exe
这里下载couchdb的最新windows安装包。
执行效果如下图所示:

能够看到在下载文件的过程中会显示当前已下载数和总的文件大小,并且有进度条显示当前下载的进度,跟wget看起来是有些神似了。下载完毕后会显示已经下载文件的情况。

作者: 付海军
出处:http://fuhj02.cnblogs.com
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接且保证内容完整!否则必究法律责任!
个人网站: http://www.fuhaijun.com/
PowerShell实现文件下载(类wget)的更多相关文章
- php 支持断点续传的文件下载类
php 支持断点续传的文件下载类 分类: php class2013-06-30 17:27 17748人阅读 评论(6) 收藏 举报 php断点续传下载http测试 php 支持断点续传,主要依靠H ...
- [上传下载] C#FileDown文件下载类 (转载)
点击下载 FileDown.zip 主要功能如下 .参数为虚拟路径 .获取物理地址 .普通下载 .分块下载 .输出硬盘文件,提供下载 支持大文件.续传.速度限制.资源占用小 看下面代码吧 /// &l ...
- php实现的支持断点续传的文件下载类
通常来说,php支持断点续传,主要依靠HTTP协议中 header HTTP_RANGE实现. HTTP断点续传原理: Http头 Range.Content-Range()HTTP头中一般断点下载时 ...
- PHP基础文件下载类的简单封装
1: <?php 2: /** 3: * [FileDown 公用文件下载方法] 4: * @param [type] $filePath [文件路径(绝对路径或相对路径)] 5: */ 6: ...
- C# 文件下载类
using System; using System.Net; using System.IO; using System.Text; using System.Web; using System.W ...
- 封装qt http文件下载类
#include <QApplication> #include <QtWidgets> #include <QtNetwork> //downloads one ...
- Linux基础命令介绍七:网络传输与安全 wget curl rsync iptables
本篇接着介绍网络相关命令:wget 文件下载工具.curl 网络数据传输工具.rsync 文件传输工具等. 本篇接着介绍网络相关命令 1.wget 文件下载工具 wget [option]... [U ...
- Android 实现网络多线程APK文件下载
(转自:http://blog.csdn.net/mad1989/article/details/38421465) 实现原理 (1)首先获得下载文件的长度,然后设置本地文件的长度. (2)根据文件长 ...
- android下载简单工具类
功能是实现下载文件,图片或MP3等,为了简单起见使用单线程,此代码为MarsAndroid教程的复制品,放在此处,留着参考. 首先是一个得到字节流随后保存到内存卡上的工具类: package com. ...
随机推荐
- struts 标签<s:ierator>的简单使用说明
struts 标签<s:ierator>的简单使用说明,只显示<s:ierator> 的前6条数据 <s:iterator value="lstVisitor& ...
- WPF快速入门系列(3)——深入解析WPF事件机制
一.引言 WPF除了创建了一个新的依赖属性系统之外,还用更高级的路由事件功能替换了普通的.NET事件. 路由事件是具有更强传播能力的事件——它可以在元素树上向上冒泡和向下隧道传播,并且沿着传播路径被事 ...
- 手机H5 web调试利器——WEINRE (WEb INspector REmote)
手机H5 web调试利器--WEINRE (WEb INspector REmote) 调试移动端页面,优先选择使用chrome浏览器调试,如果是hybrid形式的页面,可以使用chrome提供的ch ...
- java 连接 MySQL
java 连接 MySQL 1.准备工作 需要下载的工具: MySQL:http://www.mysql.com/downloads/ MySQL的可视化工具SQLyog:https://www.we ...
- 常用js方法整理common.js
项目中常用js方法整理成了common.js var h = {}; h.get = function (url, data, ok, error) { $.ajax({ url: url, data ...
- SSDB安装配置
1.下载ssdb wget -O ssdb-master.zip https://codeload.github.com/ideawu/ssdb/zip/master 2.编译安装 unzip ssd ...
- iOS开发——高级技术&签名机制
签名机制 最近看了objc.io上第17期中的文章 <Inside Code Signing> 对应的中文翻译版 <代码签名探析> ,受益颇深,对iOS代码签名机制有了进一步的 ...
- 如何在servlet取得spring beans (autowired)(转)
在应用中一般普通的JavaPojo都是由Spring来管理的,所以使用autowire注解来进行注入不会产生问题,但是有两个东西是例外的,一个是 Filter,一个是Servlet,这两样东西都是由S ...
- centos 6.4 /var/log/secure 不记录日志的問題
先确保日志服务开启:不妨重启下日志服务:由于目前RHEL 6/centos 6已经使用rsyslog替换了syslog.,所以不要在找/etc/syslog.conf了:重启命令:/etc/init. ...
- csdn 泄露用户密码害人不浅啊。
先是京东被盗,接着博客园也登陆不了了.