Perhaps the greatest strength of PowerShell is it's foundation on the .NET framework. The .NET framework enables almost unlimited possibilites inside the scripting realm. This blessing can equally be a curse as things can get complicated. Fast.

This post will describe three methods for downloading files using PowerShell - weighed up with their pros and cons.

Test setup

Today's testing is not highly scientific. The point is to show the difference in execution time and performance.

The test setup consists of PowerShell 4 running on Windows 8.1 x64 with my VDSL connection curently synced at 35.9/10.4 mbps.

I will be downloading a test file from Internode at the following URL: http://­mirror.­internode­.on.­net/­pub/­test/­10­m­e­g­.­t­e­s­t. The scripts will be executed 10 times each with the average displayed as the result.

Let's get started!

1. Invoke-WebRequest

The first and most obvious option is the Invoke-WebRequest cmdlet. It is built into PowerShell and can be used in the following method:

$url = "http://mirror.internode.on.net/pub/test/10meg.test"
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date Invoke-WebRequest -Uri $url -OutFile $output
Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"

Time taken: 27 seconds

Pros

With the cmdlet already available it is super easy to get started and use. Integration with Write-Progress is handy while watching paint dry scripts run (assuming you know the total file size). Cookies can also be persisted between mutiple requests through the use of the -Session and -WebSession parameters. 

Cons

Speed. This cmdlet is slow. From what I have observed, the HTTP response stream is buffered into memory. Once the file has been fully loaded, it is flushed to disk. This adds a huge performance hit and potential memory issues for large files. If anyone knows specifics on how this cmdlet operates, let me know!.

Another potentially serious con for this method is the reliance on Internet Explorer. For example, this cmdlet cannot be used on Windows Server Core edition servers as the Internet Explorer binaries are not included by default. In some cases you can use the -UseBasicParsing parameter, but it does not work in all cases.

Verdict

This cmdlet shines when you need to persist cookies across multiple requests (for instance HTTP Forms Auth before downloading the file).

Performance is good enough for small downloads, but there are definitely better options for situations where speed is required. If the script is to be run on a server running Windows Server Core, choose a more universal method.

2. System.Net.WebClient

A common .NET class used for downloading files is the System.Net.WebClient class.

$url = "http://mirror.internode.on.net/pub/test/10meg.test"
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date $wc = New-Object System.Net.WebClient
$wc.DownloadFile($url, $output)
#OR
(New-Object System.Net.WebClient).DownloadFile($url, $output) Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"

Time taken: 7 seconds

Pros

This method is also easy to use. Not as syntactically nice as Invoke-RestMethod - yet can still be executed on a single line. Speed is great as the HTTP response stream is buffered to disk throughout the download process.

There is also the option of System.Net.WebClient.DownloadFileAsync(). This can be very handy if you'd like your script to continue while the file downloads in parallel.

Cons

There is no visible progress indicator (or any way to query the progress mid transfer). It essentially blocks the thread until the download completes or fails. This isn't a major con, however sometimes it is handy to know how far through the transfer you are.

Verdict

System.Net.WebClient is my preferred option when file downloads are required. Anything that increases the performance of my scripts is a winner in my books. This method is also fully compatible on Server Core machines and 100% compatible with your Azure Automation runbooks.

3. Start-BitsTransfer

If you haven't heard of BITS before, check this out. BITS is primarily designed for asynchronous file downloads, but works perfectly fine synchronously too (assuming you have BITS enabled).

$url = "http://mirror.internode.on.net/pub/test/10meg.test"
$output = "$PSScriptRoot\10meg.test"
$start_time = Get-Date Import-Module BitsTransfer
Start-BitsTransfer -Source $url -Destination $output
#OR
Start-BitsTransfer -Source $url -Destination $output -Asynchronous Write-Output "Time taken: $((Get-Date).Subtract($start_time).Seconds) second(s)"

Time taken: 6 seconds

Pros

This method proved to be the fastest in my test cases! Extensive integration with Write-Progress gives you a clear indicator of the file size and progress. The -Asynchronous flag can be used to queue transfers asychronously. This method is also incredibly flexible supporting separate credentials for the destination server AND web proxy, if required.

Personally, the biggest benefit to using the Start-BitsTransfer method is the ability to set retry actions on failure and limiting the amount of bandwidth available to a transfer.

Cons

While BITS is enabled by default on many machines, you can't guarantee it is enabled on all (unless you are actively managing this). Also with the way BITS is designed, if other BITS jobs are running in the background, your job could be queued or run at a later time hindering the execution of your script.

Verdict

This method is perfect for scenarios where you want to limit the bandwidth used in a file download or where time isn't a major issue. I have used this to sync files nightly at full speed and during the day at half speed using Transfer Policies. BITS is also easy to monitor and audit.

Conclusion

We can see the obvious/easiest choice isn't always the best. I would recommend System.Net.WebClient due to it's universal nature and performance. BITS my second choice due to it's flexibility and managability.

Do you know other methods? Let me know!

https://blog.jourdant.me/post/3-ways-to-download-files-with-powershell

3 ways to download files with PowerShell的更多相关文章

  1. Asp.net core 学习笔记 ( upload/download files 文件上传与下载 )

    更新 :  2018-01-22  之前漏掉了一个 image 优化, 就是 progressive jpg refer : http://techslides.com/demos/progressi ...

  2. 安装Laravel遇到You must enable the openssl extension to download files via https问题

    刚看了一篇文章说了2014年最火的10个php框架,看到了Laravel,于是便自己试试,孰料刚安装便遇到了一个问题(由于一不小心关掉了cmd,此处无法截图显示),便是如文章标题中所说的那样,goog ...

  3. [AWS - EC2] 如何向 Amazon Linux 2 实例传输文件,下载文件。How to send/ download files from Amazon Linux 2 Instance

    1. 需要: 安装 WinSCP 2. 需要: PuTTY 生成的ppk格式密钥, 没有的话请移步此文章,完成1, 2, 3步即可. 3. 打开 WinSCP , 如果提示已经有PuTTY配置是否导入 ...

  4. How To Use XDOLoader to Manage, Download and Upload Files? (文档 ID 469585.1)

    Applies to: BI Publisher (formerly XML Publisher) - Version 5.6.3 to 5.6.3 [Release 5] Information  ...

  5. How To Use XDOLoader to Manage, Download and Upload Files? (DOC ID 469585.1)

    In this Document Goal Fix     Downloading Files   Uploading Files References Applies to: BI Publishe ...

  6. SharePoint 2013 – Workflow Manager 1.0 offline download

    [http://sharepointdeal.wordpress.com/2013/03/13/sharepoint-2013-workflow-manager-1-0-offline-downloa ...

  7. How To Download Youtube Videos Without any software

    https://www.quora.com/What-is-the-best-way-to-download-YouTube-videos-for-free There are various met ...

  8. Download/Attach source-code/java-docs with maven dependencies

    I am using Maven in my projects from last couple of years, and the automatically downloading the Jar ...

  9. 通过PowerShell命令给Azure VM添加CustomScriptExtension

    Azure的VM提供了一种管理工具叫Azure VM Extension.它实现了一些管理虚拟机所需要的重要功能,比如:重设密码.设置RDP参数.以及许多其他关键的功能,并且Azure VM一直在添加 ...

随机推荐

  1. 亚马逊CEO贝索斯致股东信:阐述公司未来计划

    亚马逊CEO 杰夫·贝索斯(Jeff Bezos)今天发布年度股东信, 详细描述了亚马逊的产品.服务和未来计划,当然,信中并没有任何的硬数据,比如说亚马逊Kindle的销量等等.但这封信也包括一些颇令 ...

  2. SQL行列轉換方法(詳細例子)

    普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法. 问题:假设有张学生成绩表(tb)如下 ...

  3. DotNetOpenAuth Part 1 : Authorization 验证服务实现及关键源码解析

    DotNetOpenAuth 是 .Net 环境下OAuth 开源实现框架.基于此,可以方便的实现 OAuth 验证(Authorization)服务.资源(Resource)服务.针对 DotNet ...

  4. mysql innodb myisam 比较

    InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...

  5. redis 常用命令 结合php

    这篇文章主要介绍了30个php操作redis常用方法代码例子,本文其实不止30个方法,可以操作string类型.list类型和set类型的数据,需要的朋友可以参考下     redis的操作很多的,以 ...

  6. “Hello World!”团队第六周的第一次会议

    今天是我们团队“Hello World!”团队第六周召开的第一次会议.博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.Todo List 六.会议照片 七.燃尽图 一.会议时间 ...

  7. OOP 2.2 构造函数

    1.概念 成员函数的一种 名字与类名相同,可以有参数,没有返回值(void也不行) 作用:对对象进行初始化,如给成员函数赋初始值 如果定义时没有构造函数,则编译器生成一个默认无参数的构造函数 默认构造 ...

  8. OOP 1.2 const关键字

    1.2 const关键字 1.常量 指针常量 定义常量:const 类型 =值 定义指针常量:const *类型=值 常量指针不可通过常量指针修改其指向的内容 可直接修改其指向的内容 常量指针的指向可 ...

  9. Alpha 冲刺(6/10)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试服务器并行能力 学习MSI.CUDA ...

  10. java程序连接MySQL数据库

    驱动程序:mysql-connector-java-5.1.7-bin.jar. 程序示例如下: package commonProject; import java.sql.Connection; ...