Home > Software engineering >  PowerShell - Copy zip file pass as string parameter to remote server
PowerShell - Copy zip file pass as string parameter to remote server

Time:06-10

I am uploading zip file using .NET Core application and pass it as a string parameter to PowerShell script and trying to use following command for copy

Invoke-Command -Session $Session -ScriptBlock { Param($uplodedZipFileAsString,$DestinationFilePath) New-Item -Path $DestinationFilePath -Value $uplodedZipFileAsString -Force }  -ArgumentList ($uplodedZipFileAsString, $DestinationFilePath)

using above command file is copied at destination location, but while tried to unzip it. it gives an error as

The Compressed (zipped) Folder 'DestPath\uplodedZipFile.zip' is invalid.

Question :-

  1. How can copy zip file(passed as string parameter) to remote server?
  2. What are the best practices should follows in this scenario?

Note:- Assume that in above PowerShell command all parameters like $Session,$uplodedZipeFileAsString and $DestinationFolderFilePath are properly provided.

Edited:-

High level code details as follows

In .NET Core using file upload control we get IFormFile file(argument name) as parameter method looks as follows

public async Task<IActionResult> Index(IFormFile file)
{
   // following method convert FileStream To Sting 
    string fileString = ConvertFileStreamToString(file); // this is zip as string

   //following method execute powershell script 
   PowerShellHelper(string fileString,... other paramter)

  //Other Code...
}

private string ConvertFileStreamToString(IFormFile file)
{
  var fileString = new StringBuilder();
  using (var reader = new StreamReader(file.OpenReadStream()))
  {
     while (reader.Peek() >= 0)
        fileString.AppendLine(reader.ReadLine());
  }
  return fileString.ToString();
}

PowerShell as follows

 function zipcopyfunction
 {
   [CmdletBinding()]
   Param
   (
    [Parameter(Mandatory=$true, 
            Position=0,
            HelpMessage='Please Provide Zip File')]
   [ValidateNotNullOrEmpty()]
   [string]$uplodedZipFileAsString,
   #other necessary paramters goes here...
  )

 #Other code related to session creation
 try
 { 
   #other code including destination file path(DestinationFilePath) and $Session...
  $DestinationFilePath = "C:\test\destFile.zip"
  Invoke-Command -Session $Session -ScriptBlock { Param($uplodedZipFileAsString,$DestinationFilePath) New-Item -Path $DestinationFilePath -Value $uplodedZipFileAsString -Force }  -ArgumentList ($uplodedZipFileAsString, $DestinationFilePath)
  #remove session related code...
}
 catch
 {
      Throw $_.exception.message
  }
}

CodePudding user response:

As commented, don't try to read a binary file as if it were a text file.

Instead, read the file as an array of bytes ([Byte[]]) to get the actual file content unaltered. Then you could change your code to do this:

# use the full, absolute filepaths as we're using .Net methods
$sourceFile   = 'D:\somewhere\TheFile.zip'

# the path (in this demo 'D:\Test') MUST exist locally in the remote machine
$destination  = 'D:\Test\TheFile.zip' 

# read the file as an array of Bytes 
[byte[]]$bytes = [System.IO.File]::ReadAllBytes($sourceFile)

Invoke-Command -Session $Session -ScriptBlock { 
    Param(
        [byte[]]$ZipBytes,
        [string]$DestinationFilePath
    ) 
    [System.IO.File]::WriteAllBytes($DestinationFilePath, $ZipBytes)
} -ArgumentList @($bytes ,$destination)

You could convert the binary data into a string, by converting the data to Base64 for instance using [Convert]::ToBase64String($bytes) but then in the scriptblock you will first need to convert that string back to bytes using [byte[]]$bytes = [Convert]::FromBase64String($uplodedZipFileAsString) and then write to file. This of course will use more processing time and the data you will be sending wil become much larger than the original number of bytes.

  • Related