Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload BIG files via HTTP

I'm trying to upload really big VM Images (5-15 Gb size) to an HTTP server using PowerShell.

I tried to use for that few methods (here links to script with net.WebClient.UploadFile and script with Invoke-webRequest)

It works well for files less than 2GB, but not for files larger than this.

I'm trying to work with httpWebRequest directly but I unable to put FileStream into it.

So my question is: how to put filestream into webrequest?

Or more generally: how to upload huge file via http with PowerShell?

$Timeout=10000000;
$fileName = "0.iso";
$data = "C:\\$fileName";
$url = "http://nexus.lab.local:8081/nexus/content/sites/myproj/$fileName";
#$buffer = [System.IO.File]::Open("$data",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read) #Err Cannot convert argument "buffer", with value: "System.IO.FileStream", for "Write" to type "System.Byte[]": 
#$buffer = gc -en byte $data # too much space in memory 
$buffer = [System.IO.File]::ReadAllBytes($data) #Limit 2gb
[System.Net.HttpWebRequest] $webRequest = [System.Net.WebRequest]::Create($url)
$webRequest.Timeout = $timeout
$webRequest.Method = "POST"
$webRequest.ContentType = "application/data"
#$webRequest.ContentLength = $buffer.Length;
$webRequest.Credentials = New-Object System.Net.NetworkCredential("admin", "admin123");

$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($buffer, 0, $buffer.Length)
$requestStream.Flush()
$requestStream.Close()

[System.Net.HttpWebResponse] $webResponse = $webRequest.GetResponse()
$streamReader = New-Object System.IO.StreamReader($webResponse.GetResponseStream())
$result = $streamReader.ReadToEnd()
return $result
$stream.Close() 
like image 511
vvchik Avatar asked Oct 20 '15 11:10

vvchik


People also ask

How can I send large files via HTTP?

We have three ways to shorten the time sending extensive data by HTTP: compress data. send chunked data. request data in a selected range.

Can HTTP upload files?

A multipart request is a HTTP request that HTTP clients construct to send files and data over to a HTTP Server. It is commonly used by browsers and HTTP clients to upload files to the server.

How can I send 20 GB for free?

MyAirBridge. With MyAirBridge(Opens in a new window), you can upload a file and email a link to a specific recipient or just upload the file and generate a link to share with anyone. You can send a file as large as 20GB for free.

How do I use HTTP to upload a file?

Configure 'HTTP Request' actionMethod (Mandatory): Select the HTTP method that you wish to use. Since we wish to upload the file, select POST method. URL (Mandatory): Enter the URL of the service to which you wish to upload the file. For this example, we will enter the URL for Built.io Backend.


2 Answers

By default HttpWebRequest is buffering data in memory. Just set HttpWebRequest.AllowWriteStreamBuffering property to false and you would be able to upload files with almost any size. See more details at msdn

like image 108
Stoune Avatar answered Oct 23 '22 19:10

Stoune


Thank you @Stoune, it was last thing that helped to receive finally working solution.

One more, it is need to organize stream file reading and writing to the webrequest buffer. And it possibly to do with that piece of code:

$requestStream = $webRequest.GetRequestStream()
$fileStream = [System.IO.File]::OpenRead($file)
$chunk = New-Object byte[] $bufSize
  while( $bytesRead = $fileStream.Read($chunk,0,$bufsize) )
  {
    $requestStream.write($chunk, 0, $bytesRead)
    $requestStream.Flush()
  }

And final script look like this:

$user = "admin"
$pass = "admin123"
$dir = "C:\Virtual Hard Disks"
$fileName = "win2012r2std.vhdx"
$file = "$dir/$fileName"
$url = "http://nexus.lab.local:8081/nexus/content/sites/myproj/$fileName"
$Timeout=10000000
$bufSize=10000

$cred = New-Object System.Net.NetworkCredential($user, $pass)

$webRequest = [System.Net.HttpWebRequest]::Create($url)
$webRequest.Timeout = $timeout
$webRequest.Method = "POST"
$webRequest.ContentType = "application/data"
$webRequest.AllowWriteStreamBuffering=$false
$webRequest.SendChunked=$true # needed by previous line
$webRequest.Credentials = $cred

$requestStream = $webRequest.GetRequestStream()
$fileStream = [System.IO.File]::OpenRead($file)
$chunk = New-Object byte[] $bufSize
  while( $bytesRead = $fileStream.Read($chunk,0,$bufsize) )
  {
    $requestStream.write($chunk, 0, $bytesRead)
    $requestStream.Flush()
  }

$responceStream = $webRequest.getresponse()
#$status = $webRequest.statuscode

$FileStream.Close()
$requestStream.Close()
$responceStream.Close()

$responceStream
$responceStream.GetResponseHeader("Content-Length") 
$responceStream.StatusCode
#$status
like image 39
vvchik Avatar answered Oct 23 '22 20:10

vvchik