【发布时间】:2015-06-19 06:52:13
【问题描述】:
我的 URL 包含多个斜杠字符 (/) 作为文件名的一部分(不是 URL)。但是当我发送http请求时,百分比编码的%2F在请求分发之前被转换为/,因此生成了错误的URL。
如何在 PowerShell 中发出忽略百分比编码值的文字 http 请求?
使用的实际网址 (Chromium browser):
我试过Invoke-WebRequest cmdlet:
Invoke-WebRequest -Uri $ChromeUrl -OutFile $FilePath -Verbose
VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64/292817/chrome-win32.zip?generation=1409504089694000&alt=media with 0-byte payload1`
未找到错误。
也试过WebClient的DownloadFile方法:
$wclient = New-Object System.Net.WebClient
$wclient.DownloadFile($ChromeUrl, $FilePath)
再次请求错误的 URL 返回 404。
解决方法 1(成功)
briantist 和 Tanuj Mathur 提供的基于反射的解决方法都非常有效。后一种:
$UrlFixSrc = @"
using System;
using System.Reflection;
public static class URLFix
{
public static void ForceCanonicalPathAndQuery(Uri uri)
{
string paq = uri.PathAndQuery;
FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
ulong flags = (ulong) flagsFieldInfo.GetValue(uri);
flags &= ~((ulong) 0x30);
flagsFieldInfo.SetValue(uri, flags);
}
}
"@
Add-Type -TypeDefinition $UrlFixSrc-Language CSharp
[URLFix]::ForceCanonicalPathAndQuery([URI]$ChromeUrl)
Invoke-WebRequest -Uri $ChromeUrl -OutFile $FilePath -Verbose
VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292640%2Fchrome-win32.zip?generation=1409351584147000&alt=media
解决方法 2(成功)
更干净的解决方案(由Tanuj Mathur 提供),但需要访问系统文件,是通过添加具有以下内容的配置文件%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
<add name="https" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
</configuration>
必须在powerhsell_ise.exe.config 中进行相应的修改才能在 ISE 中工作。
解决方法 3(失败)
我认为这是一个 System.URI 类构造函数问题,它调用隐式转换,转换转义值。尝试了重载变体Uri ([String]uriString, [Boolean]dontEscape)。但是没有区别。不管有没有dontEscape 参数,结果都是一样的。
$uri = new-object System.Uri($ChromeUrl, $true)
$uri | Format-List OriginalString, AbsoluteUri
OriginalString : https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%2F292817%2Fchrome-win32.zip?generation=1409504089694000&alt=media
AbsoluteUri : https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64/292817/chrome-win32.zip?generation=1409504089694000&alt=media
解决方法 4(失败)
还试图通过将百分比字符替换为其百分比编码值%25 来欺骗 URI 解析器。但后来它完全忽略了一切。
Invoke-WebRequest -Uri $ChromeUrl.Replace('%', '%25') -OutFile $DownloadPath -Verbose
VERBOSE: GET https://www.googleapis.com/download/storage/v1/b/chromium-browser-continuous/o/Win_x64%252F292817%252Fchrome-win32.zip?generation=1409504089694000&alt=media with 0-byte pa yload
解决方法 5(未实施)
我发现正确请求 URL 的唯一方法是通过 Internet Explorer 实例。
$ie = New-Object -ComObject InternetExplorer.Application
$ie.Visible = $true
$ie.Silent = $false
$ie.Navigate2($ChromeUrl)
但是我不知道如何自动单击“另存为”按钮并将其保存到所需的路径。另外,即使实施了,我也不觉得这是一个好的解决方案。当 IE 已经运行或从系统中卸载时会发生什么?
【问题讨论】:
-
边界疯狂。我喜欢 Powershell / 我讨厌 Powershell。非常感谢。
标签: .net url powershell uri