PowerShell Invoke-WebRequest, как автоматически использовать оригинальное имя файла?

Как я могу использовать Invoke-WebRequest для загрузки файла, но автоматически сделать имя файла таким же, как если бы я загружался через браузер? Я не нашел способ сделать работу -OutFile без указания имени файла вручную. Я в порядке с этим, используя несколько других строк кода.

Хорошее решение будет:

  • Работайте, даже если имя файла отсутствует в URL-адресе запроса. Например, URL-адрес для загрузки средств удаленной отладки Visual Studio x64 составляет http://go.microsoft.com/fwlink/?LinkId=393217, но он загружает файл rtools_setup_x64.exe.
  • Не сохраняйте весь файл в памяти перед записью на диск, если только то, что Invoke-WebRequest уже делает даже с параметром -OutFile (?)

Спасибо!

Ответ 1

В приведенном примере вам нужно будет получить перенаправленный URL-адрес, который включает в себя имя файла для загрузки. Вы можете использовать следующую функцию:

Function Get-RedirectedUrl {

    Param (
        [Parameter(Mandatory=$true)]
        [String]$URL
    )

    $request = [System.Net.WebRequest]::Create($url)
    $request.AllowAutoRedirect=$false
    $response=$request.GetResponse()

    If ($response.StatusCode -eq "Found")
    {
        $response.GetResponseHeader("Location")
    }
}

Затем это вопрос разбора имени файла с конца ответного URL (GetFileName из System.IO.Path сделает это):

$FileName = [System.IO.Path]::GetFileName((Get-RedirectedUrl "http://go.microsoft.com/fwlink/?LinkId=393217"))

Это оставит $FileName = rtools_setup_x64.exe, и вы сможете загрузить там файл.

Ответ 2

Благодаря Райану у меня есть полуиспользуемая функция:

Function Get-Url {
  param ( [parameter(position=0)]$uri )
  invoke-webrequest -uri "$uri" -outfile $(split-path -path "$uri" -leaf)
}

Графический файл и xml файл, который я смог загрузить. Когда я пытаюсь загрузить эту веб-страницу и открыть ее с помощью Edge, она будет работать время от времени.

Ответ 3

Попробуйте этот метод (может не всегда работать, потому что имя файла может отсутствовать в заголовке ответа)

  1. вызовите Invoke-WebRequest, чтобы получить результат. Затем вы можете проверить результат, чтобы посмотреть, что находится в заголовках.
  2. получить имя файла из заголовка ответа (это может быть в Headers.Location или в каком-то другом месте. Когда я выполняю свой запрос для URL, который я устранял, я обнаружил его в заголовках ["Content-Disposition"] и он выглядит как inline; filename="zzzz.docx"
  3. Создайте новый файл на основе имени и запишите содержимое в этот файл

Вот код сампе:

$result = Invoke-WebRequest -Method GET -Uri $url -Headers $headers

$contentDisposition = $result.Headers.'Content-Disposition'
$fileName = $contentDisposition.Split("=")[1].Replace("'"","")

$path = Join-Path $yourfoldername $fileName

$file = [System.IO.FileStream]::new($path, [System.IO.FileMode]::Create)
$file.write($result.Content, 0, $result.RawContentLength)
$file.close()

Ответ 4

Суть моего кода - это работает.. используя PS 5.1

Я прокомментировал нормальное утверждение -Outfile, потому что это означало бы, что я знал имя файла заранее. Я соединил это, основываясь на нескольких источниках, существует множество способов парсинга заголовков Content-Disposition, поэтому используйте все, что вам подходит.

$outpath = "C:\\temp\\"

Вызов:

$result = Invoke-WebRequest -method GET -Uri $resourceUrl -Headers 
$resourceHeaders -Verbose #-OutFile $($outPath+"$nodeId.pdf")

разбор

$outFilename = $outpath+$result.Headers.'Content-Disposition'.Split("=")[1].Split('\\""')[1] #shaky parsing - might require improvement in time

Написание файла (это в основном PDF для меня

[System.IO.File]::WriteAllBytes($outFilename, $result.content)

Ответ 5

powershell.exe Invoke-WebRequest -Uri serverIP/file.exe -OutFile C:\Users\file.exe