mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Allow using a folder path in WebCmdlet's OutFile parameter (#19007)
This commit is contained in:
+6
-2
@@ -135,8 +135,12 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
else if (ShouldSaveToOutFile)
|
||||
{
|
||||
StreamHelper.SaveStreamToFile(baseResponseStream, QualifiedOutFile, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
|
||||
{
|
||||
string outFilePath = WebResponseHelper.GetOutFilePath(response, _qualifiedOutFile);
|
||||
|
||||
WriteVerbose(string.Create(System.Globalization.CultureInfo.InvariantCulture, $"File Name: {Path.GetFileName(_qualifiedOutFile)}"));
|
||||
|
||||
StreamHelper.SaveStreamToFile(baseResponseStream, outFilePath, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(StatusCodeVariable))
|
||||
|
||||
+13
-1
@@ -484,6 +484,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
internal string QualifiedOutFile => QualifyFilePath(OutFile);
|
||||
|
||||
internal string _qualifiedOutFile;
|
||||
|
||||
internal bool ShouldCheckHttpStatus => !SkipHttpErrorCheck;
|
||||
|
||||
/// <summary>
|
||||
@@ -852,7 +854,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
|
||||
// Output ??
|
||||
if (PassThru && OutFile is null)
|
||||
if (PassThru.IsPresent && OutFile is null)
|
||||
{
|
||||
ErrorRecord error = GetValidationError(WebCmdletStrings.OutFileMissing, "WebCmdletOutFileMissingException", nameof(PassThru));
|
||||
ThrowTerminatingError(error);
|
||||
@@ -864,6 +866,15 @@ namespace Microsoft.PowerShell.Commands
|
||||
ErrorRecord error = GetValidationError(WebCmdletStrings.OutFileMissing, "WebCmdletOutFileMissingException", nameof(Resume));
|
||||
ThrowTerminatingError(error);
|
||||
}
|
||||
|
||||
_qualifiedOutFile = ShouldSaveToOutFile ? QualifiedOutFile : null;
|
||||
|
||||
// OutFile must not be a directory to use Resume.
|
||||
if (Resume.IsPresent && Directory.Exists(_qualifiedOutFile))
|
||||
{
|
||||
ErrorRecord error = GetValidationError(WebCmdletStrings.ResumeNotFilePath, "WebCmdletResumeNotFilePathException", _qualifiedOutFile);
|
||||
ThrowTerminatingError(error);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void PrepareSession()
|
||||
@@ -1093,6 +1104,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
if (Resume.IsPresent)
|
||||
{
|
||||
FileInfo fileInfo = new(QualifiedOutFile);
|
||||
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
request.Headers.Range = new RangeHeaderValue(fileInfo.Length, null);
|
||||
|
||||
+5
-1
@@ -56,7 +56,11 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
if (ShouldSaveToOutFile)
|
||||
{
|
||||
StreamHelper.SaveStreamToFile(responseStream, QualifiedOutFile, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
|
||||
string outFilePath = WebResponseHelper.GetOutFilePath(response, _qualifiedOutFile);
|
||||
|
||||
WriteVerbose(string.Create(System.Globalization.CultureInfo.InvariantCulture, $"File Name: {Path.GetFileName(_qualifiedOutFile)}"));
|
||||
|
||||
StreamHelper.SaveStreamToFile(responseStream, outFilePath, this, response.Content.Headers.ContentLength.GetValueOrDefault(), _cancelToken.Token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Microsoft.PowerShell.Commands
|
||||
@@ -34,6 +35,14 @@ namespace Microsoft.PowerShell.Commands
|
||||
return headers;
|
||||
}
|
||||
|
||||
internal static string GetOutFilePath(HttpResponseMessage response, string _qualifiedOutFile)
|
||||
{
|
||||
// Get file name from last segment of Uri
|
||||
string lastUriSegment = System.Net.WebUtility.UrlDecode(response.RequestMessage.RequestUri.Segments[^1]);
|
||||
|
||||
return Directory.Exists(_qualifiedOutFile) ? Path.Join(_qualifiedOutFile, lastUriSegment) : _qualifiedOutFile;
|
||||
}
|
||||
|
||||
internal static string GetProtocol(HttpResponseMessage response) => string.Create(CultureInfo.InvariantCulture, $"HTTP/{response.Version}");
|
||||
|
||||
internal static int GetStatusCode(HttpResponseMessage response) => (int)response.StatusCode;
|
||||
|
||||
@@ -203,6 +203,9 @@
|
||||
</data>
|
||||
<data name="ReadResponseProgressStatus" xml:space="preserve">
|
||||
<value>Downloaded: {0} of {1}</value>
|
||||
</data>
|
||||
<data name="ResumeNotFilePath" xml:space="preserve">
|
||||
<value>The Resume switch can only be used if OutFile targets a file but it resolves to a directory: {0}.</value>
|
||||
</data>
|
||||
<data name="SessionConflict" xml:space="preserve">
|
||||
<value>The cmdlet cannot run because the following conflicting parameters are specified: Session and SessionVariable. Specify either Session or SessionVariable, then retry.</value>
|
||||
|
||||
@@ -735,6 +735,19 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
|
||||
$jsonContent.headers.Host | Should -Be $uri.Authority
|
||||
}
|
||||
|
||||
It "Invoke-WebRequest -OutFile folder Downloads the file and names it" {
|
||||
$uri = Get-WebListenerUrl -Test 'Get'
|
||||
$content = Invoke-WebRequest -Uri $uri
|
||||
$outFile = Join-Path $TestDrive $content.BaseResponse.RequestMessage.RequestUri.Segments[-1]
|
||||
|
||||
# ensure the file does not exist
|
||||
Remove-Item -Force -ErrorAction Ignore -Path $outFile
|
||||
Invoke-WebRequest -Uri $uri -OutFile $TestDrive
|
||||
|
||||
Test-Path $outFile | Should -Be $true
|
||||
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $content.Content.Length
|
||||
}
|
||||
|
||||
It "Invoke-WebRequest should fail if -OutFile is <Name>." -TestCases @(
|
||||
@{ Name = "empty"; Value = [string]::Empty }
|
||||
@{ Name = "null"; Value = $null }
|
||||
@@ -2000,6 +2013,11 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
|
||||
Should -Throw -ErrorId 'WebCmdletOutFileMissingException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
|
||||
}
|
||||
|
||||
It "Invoke-WebRequest -Resume should fail if -OutFile folder" {
|
||||
{ Invoke-WebRequest -Resume -Uri $resumeUri -OutFile $TestDrive -ErrorAction Stop } |
|
||||
Should -Throw -ErrorId 'WebCmdletResumeNotFilePathException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand'
|
||||
}
|
||||
|
||||
It "Invoke-WebRequest -Resume Downloads the whole file when the file does not exist" {
|
||||
$response = Invoke-WebRequest -Uri $resumeUri -OutFile $outFile -Resume -PassThru
|
||||
|
||||
@@ -2691,6 +2709,19 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
|
||||
$jsonContent.headers.Host | Should -Be $uri.Authority
|
||||
}
|
||||
|
||||
It "Invoke-RestMethod -OutFile folder Downloads the file and names it" {
|
||||
$uri = Get-WebListenerUrl -Test 'Get'
|
||||
$content = Invoke-WebRequest -Uri $uri
|
||||
$outFile = Join-Path $TestDrive $content.BaseResponse.RequestMessage.RequestUri.Segments[-1]
|
||||
|
||||
# ensure the file does not exist
|
||||
Remove-Item -Force -ErrorAction Ignore -Path $outFile
|
||||
Invoke-RestMethod -Uri $uri -OutFile $TestDrive
|
||||
|
||||
Test-Path $outFile | Should -Be $true
|
||||
Get-Item $outFile | Select-Object -ExpandProperty Length | Should -Be $content.Content.Length
|
||||
}
|
||||
|
||||
It "Invoke-RestMethod should fail if -OutFile is <Name>." -TestCases @(
|
||||
@{ Name = "empty"; Value = [string]::Empty }
|
||||
@{ Name = "null"; Value = $null }
|
||||
@@ -3881,6 +3912,11 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
|
||||
Should -Throw -ErrorId 'WebCmdletOutFileMissingException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
|
||||
}
|
||||
|
||||
It "Invoke-RestMethod -Resume should fail if -OutFile folder" {
|
||||
{ Invoke-RestMethod -Resume -Uri $resumeUri -OutFile $TestDrive -ErrorAction Stop } |
|
||||
Should -Throw -ErrorId 'WebCmdletResumeNotFilePathException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand'
|
||||
}
|
||||
|
||||
It "Invoke-RestMethod -Resume Downloads the whole file when the file does not exist" {
|
||||
# ensure the file does not exist
|
||||
Remove-Item -Force -ErrorAction 'SilentlyContinue' -Path $outFile
|
||||
|
||||
Reference in New Issue
Block a user