Functions/Get-FileName.ps1
[CmdletBinding()] param ( [Parameter(Mandatory)] [uri] $Uri, [ValidateNotNullOrEmpty()] [string] $UserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', [string] $Referer ) Set-HttpClient -Uri $Uri Write-Host ('{0}からファイル名を取得します。' -f $Uri.AbsoluteUri) -ForegroundColor Cyan $global:HttpClient.DefaultRequestHeaders.Add('User-Agent', $UserAgent) if ($Referer) { $global:HttpClient.DefaultRequestHeaders.Add('Referer', $Referer) } $httpHeader = $global:HttpClient.GetAsync($Uri, 1) if ($httpHeader.Result.StatusCode -ne 'OK') { throw 'ファイル名取得の為にリクエストを送りましたが、正常に完了しませんでした。' } $contentType = $httpHeader.Result.Content.Headers.ContentType.MediaType if ($contentType -eq 'text/html') { throw 'HTTPヘッダのContent-Typeがtext/htmlでした。' } # ContentDispositionから取得 $ContentDispositionFileName = [regex]::Replace($httpHeader.Result.Content.Headers.ContentDisposition.FileName, '"', '') if ($ContentDispositionFileName) { return $ContentDispositionFileName } # リダイレクト後のリクエストURIの葉から取得 $RequestUri = $httpHeader.Result.RequestMessage.RequestUri $RequestUriLeaf = $RequestUri.LocalPath | Split-Path -Leaf if (!$RequestUriLeaf -match '.+\..+') { Write-Warning '取得したファイル名に拡張子がありませんでした。取得に失敗した可能性があります。' } return $RequestUriLeaf <# .SYNOPSIS ダウンロード時のファイル名を取得します。 .DESCRIPTION ダウンロード時のファイル名を取得します。 レスポンスヘッダのContent-Typeがtext/htmlとなるものに対しては例外を投げます。 .PARAMETER Uri ファイルのダウンロードリンクを指定します。 .PARAMETER UserAgent HTTPリクエストの為のユーザエージェントを指定します。 .PARAMETER Referer HTTPリクエストの為のリファラを指定します。 .INPUTS なし .OUTPUTS System.String ダウンロードする際のファイル名を返します。 .EXAMPLE PS C:\>Get-FileName -Uri 'https://go.microsoft.com/fwlink/?LinkID=799445' この例では、Windows Update Assistantのインストーラのファイル名を取得します。 .LINK .NOTES curlでの実装を考えたが、httpヘッダを取得した時点でリクエストを完了とする方法が分からなかった。 -IオプションでのHEADリクエストは拒否するサーバーがあるので不可。 curlでHTTPヘッダを取得する場合は以下のようにします。 $httpHeader = curl -sL -D - -o /dev/null $Uri #> |