how to use ZoomNet DownloadFileAsync - vb.net

I'm using a Nuget package Jericho /ZoomNet, trying to download a zoom recording (mp4) [winform App]
I'm not sure how the DownloadFileAsync() works to save the File from the Stream, I keep getting task cancelled exception
Can you point to any similar examples ?
UPDATE
So i talked to the Author of the package,
he made a beta release to download large files more efficiently, and also showed me you can add your own client object to control the timeout according to file size, also using the ConfigureAwait(False) was necessary.
Dim myHttpClient = New HttpClient() With {
.Timeout = TimeSpan.FromMinutes(10) }
Dim azoomClient = New ZoomClient(connectionInfo,
myHttpClient)
Dim sourceStream = Await
azoomClient.CloudRecordings.DownloadFileAsync(fdownloadFileName, ct).ConfigureAwait(False)
Using outStream = File.OpenWrite(DestFileName)
sourceStream.CopyTo(outStream)
End Using
This is the code I've tried
Private azoomClient = New ZoomClient(connectionInfo)
Dim fdownloadFileName As String = "c:\zoomrec1.mp4"
Dim ct As New Threading.CancellationToken
Dim sourceStream As Stream
sourceStream = Await azoomClient.CloudRecordings.DownloadFileAsync(fdownloadFileName, ct).ConfigureAwait(False)
DumpStream(sourceStream, DestFileName)
Private Async Function DumpStream(ByVal outStream As Stream, ByVal outputFileName As String) As Task
Try
' Dump the contents of a stream to a file
outStream.Flush()
Dim SavePos As Long = outStream.Position ' Save the original position in the stream
outStream.Seek(0, SeekOrigin.Begin)
Dim f As Stream = File.OpenWrite(outputFileName)
CopyStream(outStream, f)
outStream.Position = SavePos ' Go back to the original postion in the stream
f.Close()
Catch ex As Exception
MessageBox.Show("Error:DumpStream()>" & ex.Message)
End Try
End Function
Public Shared Sub CopyStream(ByVal input As Stream, ByVal output As Stream)
Try
' Copy the contents of one stream to another stream
Dim buf As Byte() = New Byte(8 * 1024 - 1) {} ' A buffer for storing data while copying
Dim len As Integer
len = input.Read(buf, 0, buf.Length)
While len > 0
output.Write(buf, 0, len)
len = input.Read(buf, 0, buf.Length)
End While
Catch ex As Exception
MessageBox.Show("Error:CopyStream()>" & ex.Message)
End Try
End Sub
'''
i can get the download url filename with this call,
'''
Dim apiKey = "abc" Dim apiSecret = "123"
Dim connectionInfo As New JwtConnectionInfo(apiKey, apiSecret)
Dim v As Object = azoomClient.CloudRecordings.GetRecordingInformationAsync(MeetingID)
Dim modelsRecording = Await v
downloadFileName = CStr(modelsRecording.RecordingFiles.Where(Function(z)
z.FileType = Models.RecordingFileType.Video)(0).DownloadUrl)
'''

I updated the code above with a working solution.

Related

Can't read an XML in Stream

I have a little problem with an XML file and a Stream. I create and save an XML file in a Stream, encrypt the Stream and then save it to a normal file.
I want to read this XML, however I can only do this if I use a FileStream and write a decrypted file to disk.
Is there a way to decrypt and keep this file in memory?
This is my code:
XMLDecriptato = New MemoryStream()
Using stream_readerX As New StreamReader(XMLDecriptato, Text.Encoding.UTF8)
XMLDecriptato.SetLength(0)
Dim FStreamCrypted As FileStream = File.Open(varTitolo, FileMode.Open, FileAccess.Read)
FStreamCrypted.Seek(0, SeekOrigin.Begin)
CryptStream(Pass, FStreamCrypted, XMLDecriptato, Type.Decrypt)
'try to read the stream
Dim xDocumentX As New XmlDocument()
xDocumentX.Load(stream_readerX) 'here is the error
End Using
It keeps saying that the Stream is closed. I have tried also another way. The only one that works is to write the stream to the hard disk with a FileStream.
And that is the Encrypt/Decrypt Sub:
Public Sub CryptStream(ByVal Psw As String, ByVal IN_Stream As Stream, ByVal OUT_Stream As Stream, ByVal CrtType As CryptType)
Dim AES_Provider As New AesCryptoServiceProvider()
Dim Key_Size_Bits As Integer = 0
For i As Integer = 1024 To 1 Step -1
If (aes_provider.ValidKeySize(i)) Then
Key_Size_Bits = i
Exit For
End If
Next i
Dim Block_Size_Bits As Integer = AES_Provider.BlockSize
Dim Key() As Byte = Nothing
Dim IV() As Byte = Nothing
Dim Salt() As Byte = "//my salt//"
MakeKeyAndIV(Psw, Salt, Key_Size_Bits, Block_Size_Bits, Key, IV)
Dim Crypto_Transform As ICryptoTransform = Nothing
Select Case CrtType
Case CryptType.Encrypt
Crypto_Transform = AES_Provider.CreateEncryptor(key, iv)
Case CryptType.Decrypt
Crypto_Transform = AES_Provider.CreateDecryptor(key, iv)
End Select
If Crypto_Transform Is Nothing Then Exit Sub
Try
Using Crypto_Stream As New CryptoStream(OUT_Stream, Crypto_Transform, CryptoStreamMode.Write)
Const Block_Size As Integer = 1024
Dim Buffer(Block_Size) As Byte
Dim Bytes_Read As Integer
Do
Bytes_Read = IN_Stream.Read(Buffer, 0, Block_Size)
If (Bytes_Read = 0) Then Exit Do
Crypto_Stream.Write(Buffer, 0, Bytes_Read)
Loop
End Using
Catch ex As Exception
End Try
Crypto_Transform.Dispose()
End Sub
It turns out that when CryptoStream.Dispose() is called by the Using/End Using block, the CryptoStream also disposes the underlying stream (in this case your MemoryStream). This behaviour can be confirmed by checking Microsoft's Reference Source.
Since the CryptoStream doesn't have a LeaveOpen flag like the StreamReader does since .NET 4.5 and up, I removed the Using block and wrote the necessary calls on my own for your method.
The changes:
Public Sub CryptStream(ByVal Psw As String, ByVal IN_Stream As Stream, ByVal OUT_Stream As Stream, ByVal CrtType As CryptType, Optional ByVal LeaveOpen As Boolean = False)
...code...
Try
Dim Crypto_Stream As New CryptoStream(OUT_Stream, Crypto_Transform, CryptoStreamMode.Write)
Const Block_Size As Integer = 1024
Dim Buffer(Block_Size) As Byte
Dim Bytes_Read As Integer
Do
Bytes_Read = IN_Stream.Read(Buffer, 0, Block_Size)
If (Bytes_Read = 0) Then Exit Do
Crypto_Stream.Write(Buffer, 0, Bytes_Read)
Loop
If Crypto_Stream.HasFlushedFinalBlock = False Then Crypto_Stream.FlushFinalBlock()
If LeaveOpen = False Then
Crypto_Stream.Dispose()
End If
Catch ex As Exception
End Try
...code...
End Sub
And since data will be fed into the MemoryStream its position will have changed, so you have to reset that too before loading the XML document:
XMLDecriptato = New MemoryStream()
Using stream_readerX As New StreamReader(XMLDecriptato, System.Text.Encoding.UTF8)
Dim FStreamCrypted As FileStream = File.Open(OpenFileDialog1.FileName, FileMode.Open, FileAccess.Read)
CryptStream(Pass, FStreamCrypted, XMLDecriptato, CryptType.Decrypt, True) 'True = Leave the underlying stream open.
XMLDecriptato.Seek(0, SeekOrigin.Begin) 'Reset the MemoryStream's position.
Dim xDocumentX As New XmlDocument()
xDocumentX.Load(stream_readerX)
End Using
As you might have noticed I removed the FStreamCrypted.Seek(0, SeekOrigin.Begin) line. This was because you've just opened the stream and done nothing with it, so the position will already be at 0.
Hope this helps!

Error handling in a callback in vb.net

New to asynchronous calls, in this case using a call back. The code below works.
The code is calling a rather rudimentary web service which returns xml. If the service returns xml the code works fine and msresponse is filled with the xml and the funcion "GetWebserviceData" is able to return, to the caller, a parsed msresponse through the function "CreateDT_Implantable_Device". This works without a hitch as long as xml is returned.
If the service does not return any xml there is an error thrown at this line in the respcallback:
" Dim resp As HttpWebResponse = _
CType(req.EndGetResponse(ar), HttpWebResponse)"
The error that is thrown is "400-bad request)"
It seems that if the service fails the thread for the callback does not complete correctly and the entire application locks up at that point. It returns to the vb.net form that called "GetWebserviceData" and none of the controls work: the form is frozen.
I have tried putting try catches around all the code in call back function (as seen below), "respcallback" and around all the code in "GetWebserviceData" (not in the code below). as you can see from the try catch in "respcallback" in case of this error I am trying to end the callback thread and fill msResponse so the loop in "GetWebserviceData" that follows is satisfied and will end. Here is the loop.
Do While msResponse.Length = 0
'wait
Loop
The complete code follows: Any help would be appreciated. I am trying allow the webservice to fail, let the code continue and put up a messagebox saying the service failed. Obviously my try catch is not working as seen in "respcallback"; the code simply locks up.
Code follows. Any help would be appreciated:
Public Function GetWebserviceData(psUDI As String) As DataTable
FillGS1Delimeters()
miUDI = psUDI
' Create the request object.
'Try
Dim wreq As HttpWebRequest = _
CType(WebRequest.Create("https://accessgudid.nlm.nih.gov/api/v1/devices/lookup.xml?udi=" & psUDI), HttpWebRequest)
' Create the state object.
Dim rs As RequestState = New RequestState()
' Put the request into the state so it can be passed around...
rs.Request = wreq
' Issue the async request..
Dim r As IAsyncResult = _
CType(wreq.BeginGetResponse( _
New AsyncCallback(AddressOf RespCallback), rs), IAsyncResult)
' Wait until the ManualResetEvent is set so that the application
' does not exit until after the callback is called.
allDone.WaitOne()
Do While msResponse.Length = 0
'wait
Loop
'Catch ex As Exception
'msResponse = "Error"
'MessageBox.Show("an error")
'End Try
Return CreateDT_Implantable_Device(msResponse)
End Function
Private Function CreateDT_Implantable_Device(wsResponse As String)
Dim dtDevice As DataTable = New DataTable()
Dim dtPI As DataTable = New DataTable()
Dim ds As DataSet = New DataSet
createEmptyDeviceTable(dtDevice)
createEmptyPITable(dtPI)
ds = StoreXMLAsText(msResponse)
dtPI = FillRecord(dtDevice, ds)
Return dtPI
End Function
Shared Sub RespCallback(ar As IAsyncResult)
Try
' Get the RequestState object from the async result.
Dim rs As RequestState = CType(ar.AsyncState, RequestState)
' Get the HttpWebRequest from RequestState..
Dim req As HttpWebRequest = rs.Request
' Call EndGetResponse, which returns the HttpWebResponse object
' that came from the request issued above.
Dim resp As HttpWebResponse = _
CType(req.EndGetResponse(ar), HttpWebResponse)
' Start reading data from the respons stream.
Dim ResponseStream As Stream = resp.GetResponseStream()
' Store the reponse stream in RequestState to read
' the stream asynchronously.
rs.ResponseStream = ResponseStream
' Pass rs.BufferRead to BeginRead. Read data into rs.BufferRead.
Dim iarRead As IAsyncResult = _
ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, _
New AsyncCallback(AddressOf ReadCallBack), rs)
Catch ex As Exception
msResponse = "Invalid UDI"
MessageBox.Show(ex.Message)
msResponse = "Error"
End Try
End Sub
Shared Sub ReadCallBack(asyncResult As IAsyncResult)
' Get the RequestState object from the AsyncResult.
Dim rs As RequestState = CType(asyncResult.AsyncState, RequestState)
' Retrieve the ResponseStream that was set in RespCallback.
Dim responseStream As Stream = rs.ResponseStream
' Read rs.BufferRead to verify that it contains data.
Dim read As Integer = responseStream.EndRead(asyncResult)
If read > 0 Then
' Prepare a Char array buffer for converting to Unicode.
Dim charBuffer(1024) As Char
' Convert byte stream to Char array and then String.
' len contains the number of characters converted to Unicode.
Dim len As Integer = _
rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0)
Dim str As String = New String(charBuffer, 0, len)
' Append the recently read data to the RequestData stringbuilder
' object contained in RequestState.
rs.RequestData.Append( _
Encoding.ASCII.GetString(rs.BufferRead, 0, read))
' Continue reading data until responseStream.EndRead
' returns –1.
Dim ar As IAsyncResult = _
responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, _
New AsyncCallback(AddressOf ReadCallBack), rs)
Else
If rs.RequestData.Length > 1 Then
' Display data to the console.
Dim strContent As String
strContent = rs.RequestData.ToString()
msResponse = strContent
Console.WriteLine(strContent)
End If
' Close down the response stream.
responseStream.Close()
' Set the ManualResetEvent so the main thread can exit.
allDone.Set()
End If
Return
End Sub
Here is what you want to reference from MSDN.
https://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
Seems it would be much easier using Async and Await tho...

System.FormatException On ConvertFromBase64String

This is such a great place to ask questions!
I'm facing one problem.
I'm trying to send an image from an AutoIT client over to a server that is written in VB.NET
Here is the code for the AutoIT Client:
TCPStartup()
$MainSocket = TCPConnect("127.0.0.1", 9832)
$PATH = _ScreenCapture_Capture("")
$Data2Send = "RemoteDESK|" & _Base64Encode(HBITMAP_To_Bytes($PATH)) & "<EOF>"
TCPSend($MainSocket, $Data2Send)
And here is the code for the VB.NET server:
Data handler:
Private Sub GotInfo(ByVal Data As String, ByVal Sender As Socket)
Dim Cut() As String = Data.Split("|")
Select Case Cut(0)
Case "RemoteDESK"
Dim ImgString As String = Cut(1)
PictureBox1.Image = B64ToImage(ImgString)
End Select
End Sub
Base 64 String to Image Fucntion:
Private Function B64ToImage(ByVal B64 As String) As Image
Dim ByAr() As Byte = Convert.FromBase64String(B64) 'Exception Happens here
Dim img As Image
Dim MS As New MemoryStream(ByAr)
Try
img = Image.FromStream(MS)
Catch ex As Exception
Return Nothing
End Try
Return img
End Function
The OnReceive Sub:
Private Sub OnReceive(ByVal ar As IAsyncResult)
Dim Content As String = String.Empty
Dim State As StateObject = DirectCast(ar.AsyncState, StateObject)
Dim Handler As Socket = State._MySocket
Try
Dim BytesRead As Integer = Handler.EndReceive(ar)
If BytesRead > 0 Then
State._SB.Append(Encoding.ASCII.GetString(State.Data))
Content = State._SB.ToString
If Content.IndexOf("<EOF>") > -1 Then
Dim ReadContent As String = Content.Remove(Content.IndexOf("<EOF>"))
RaiseEvent GotInfo(ReadContent, State._MySocket)
Else
Handler.BeginReceive(State.Data, 0, State.BufferSize, SocketFlags.None, New AsyncCallback(AddressOf OnReceive), State)
End If
End If
Catch ex As Exception
RaiseEvent ClientDC(Handler)
End Try
End Sub
Alright, so now I used a text comparing tool, and every time on line 53, the received string has changed, as in the the 2 lines of text are on the same line compared to the autoit's output.
The autoit output is the readable one.

Save file if error reading with Stream Reader

I am trying to parse a uploaded txt file. I need to save the file if there is an error parsing it. The problem is that the parser is using a Stream Reader and if an error occurs it just saves the empty file and not the file contents.
Dim file As HttpPostedFile = context.Request.Files(0)
If Not IsNothing(file) AndAlso file.ContentLength > 0 AndAlso Path.GetExtension(file.FileName) = ".txt" Then
Dim id As Integer = (Int32.Parse(context.Request("id")))
Try
ParseFile(file, id)
context.Response.Write("success")
Catch ex As Exception
Dim filename As String = file.FileName
Dim uploadPath = context.Server.MapPath("~/Errors/MyStudentDataFiles/")
file.SaveAs(uploadPath + id.ToString() + filename)
End Try
Else
context.Response.Write("error")
End If
My ParseFile method is something like this
Protected Sub ParseFile(ByVal studentLoanfile As HttpPostedFile, ByVal id As Integer)
Using r As New StreamReader(studentLoanfile.InputStream)
line = GetLine(r)
End Using
End Sub
Is there a way to Clone the file before it gets passed into the parseFile sub or a way to read the file without loosing the contents?
Thanks in advance
For anyone who runs into this problem in the future, I ended up reading the file to the end and saving it into a variable. Then converted it back into a memory stream to use for the parser. If an error occurs, I just create a new file with the string. This is the code I used.
Dim id As Integer = (Int32.Parse(context.Request("id")))
'Read full file for error logging
Dim content As String = [String].Empty
Using sr = New StreamReader(uploadedFile.InputStream)
content = sr.ReadToEnd()
End Using
'Convert it back into a stream
Dim byteArray As Byte() = Encoding.UTF8.GetBytes(content)
Dim stream As New MemoryStream(byteArray)
Try
ParseFile(stream, id, content)
context.Response.Write("success")
Catch ex As Exception
Dim filename As String = uploadedFile.FileName
Dim uploadPath = context.Server.MapPath("~/Errors/MyStudentDataFiles/")
'Save full file on error
Using sw As StreamWriter = File.CreateText(uploadPath + id.ToString() + filename)
sw.WriteLine(content)
End Using
context.Response.Write("error")
Throw ex
End Try
Else
context.Response.Write("error")
End If

VB.NET - download zip in Memory and extract file from memory to disk

I'm having some trouble with this, despite finding examples. I think it may be an encoding problem, but I'm just not sure. I am trying to programitally download a file from a https server, that uses cookies (and hence I'm using httpwebrequest). I'm debug printing the capacity of the streams to check, but the output [raw] files look different. Have tried other encoding to no avail.
Code:
Sub downloadzip(strURL As String, strDestDir As String)
Dim request As HttpWebRequest
Dim response As HttpWebResponse
request = Net.HttpWebRequest.Create(strURL)
request.UserAgent = strUserAgent
request.Method = "GET"
request.CookieContainer = cookieJar
response = request.GetResponse()
If response.ContentType = "application/zip" Then
Debug.WriteLine("Is Zip")
Else
Debug.WriteLine("Is NOT Zip: is " + response.ContentType.ToString)
Exit Sub
End If
Dim intLen As Int64 = response.ContentLength
Debug.WriteLine("response length: " + intLen.ToString)
Using srStreamRemote As StreamReader = New StreamReader(response.GetResponseStream(), Encoding.Default)
'Using ms As New MemoryStream(intLen)
Dim fullfile As String = srStreamRemote.ReadToEnd
Dim memstream As MemoryStream = New MemoryStream(New UnicodeEncoding().GetBytes(fullfile))
'test write out to flie
Dim data As Byte() = memstream.ToArray()
Using filestrm As FileStream = New FileStream("c:\temp\debug.zip", FileMode.Create)
filestrm.Write(data, 0, data.Length)
End Using
Debug.WriteLine("Memstream capacity " + memstream.Capacity.ToString)
'Dim strData As String = srStreamRemote.ReadToEnd
memstream.Seek(0, 0)
Dim buffer As Byte() = New Byte(2048) {}
Using zip As New ZipInputStream(memstream)
Debug.WriteLine("zip stream cap " + zip.Length.ToString)
zip.Seek(0, 0)
Dim e As ZipEntry
Dim flag As Boolean = True
Do While flag ' daft, but won't assign e=zip... tries to evaluate
e = zip.GetNextEntry
If IsNothing(e) Then
flag = False
Exit Do
Else
e.UseUnicodeAsNecessary = True
End If
If Not e.IsDirectory Then
Debug.WriteLine("Writing out " + e.FileName)
' e.Extract(strDestDir)
Using output As FileStream = File.Open(Path.Combine(strDestDir, e.FileName), _
FileMode.Create, FileAccess.ReadWrite)
Dim n As Integer
Do While (n = zip.Read(buffer, 0, buffer.Length) > 0)
output.Write(buffer, 0, n)
Loop
End Using
End If
Loop
End Using
'End Using
End Using 'srStreamRemote.Close()
response.Close()
End Sub
So I get the right size file downloaded, but dotnetzip does not recognise it, and the files that get copied out are incomplete/invalid zips. I've spent most of today on this, and am ready to give up.
I think the answer will be to break down the problem, and perhaps change a couple aspects in the code.
For example, lets get rid of converting the response stream to a string:
Dim memStream As MemoryStream
Using rdr As System.IO.Stream = response.GetResponseStream
Dim count = Convert.ToInt32(response.ContentLength)
Dim buffer = New Byte(count) {}
Dim bytesRead As Integer
Do
bytesRead += rdr.Read(buffer, bytesRead, count - bytesRead)
Loop Until bytesRead = count
rdr.Close()
memStream = New MemoryStream(buffer)
End Using
Next, there's an easier way to output the contents of a memory stream to a file. Consider your code
Dim data As Byte() = memstream.ToArray()
Using filestrm As FileStream = New FileStream("c:\temp\debug.zip", FileMode.Create)
filestrm.Write(data, 0, data.Length)
End Using
can be replaced with
Using filestrm As FileStream = New FileStream("c:\temp\debug.zip", FileMode.Create)
memstream.WriteTo(filestrm)
End Using
That eliminates the need to transfer your memory stream into another byte array, and then push the byte array down the stream, when in fact the memory stream can transfer data directly to file (via the filestream) saving the middle-man buffer.
I'll admit I haven't worked with the Zip/compression libraries you're using, but with the above amendments you have removed unnecessary transfers between streams, byte arrays, strings, etc, and hopefully eliminated the encoding issues you were having.
Give that a try and let us know how you get on. Consider attempting to open the file that you saved ("C:\temp\debug.zip") to see if it is listed as corrupt. If not, then you know at least as far as that in the code, it is working ok.
I thought I'd post my full working solution to my own question, it combines the two excellent replies I've had, thank you guys.
Sub downloadzip(strURL As String, strDestDir As String)
Try
Dim request As HttpWebRequest
Dim response As HttpWebResponse
request = Net.HttpWebRequest.Create(strURL)
request.UserAgent = strUserAgent
request.Method = "GET"
request.CookieContainer = cookieJar
response = request.GetResponse()
If response.ContentType = "application/zip" Then
Debug.WriteLine("Is Zip")
Else
Debug.WriteLine("Is NOT Zip: is " + response.ContentType.ToString)
Exit Sub
End If
Dim intLen As Int32 = response.ContentLength
Debug.WriteLine("response length: " + intLen.ToString)
Dim memStream As MemoryStream
Using stmResponse As IO.Stream = response.GetResponseStream()
'Using ms As New MemoryStream(intLen)
Dim buffer = New Byte(intLen) {}
'Dim memstream As MemoryStream = New MemoryStream(buffer)
Dim bytesRead As Integer
Do
bytesRead += stmResponse.Read(buffer, bytesRead, intLen - bytesRead)
Loop Until bytesRead = intLen
memStream = New MemoryStream(buffer)
Dim res As Boolean = False
res = ZipExtracttoFile(memStream, strDestDir)
End Using 'srStreamRemote.Close()
response.Close()
Catch ex As Exception
'to do :)
End Try
End Sub
Function ZipExtracttoFile(strm As MemoryStream, strDestDir As String) As Boolean
Try
Using zip As ZipFile = ZipFile.Read(strm)
For Each e As ZipEntry In zip
e.Extract(strDestDir)
Next
End Using
Catch ex As Exception
Return False
End Try
Return True
End Function
You can download into a MemoryStream, then examine it:
Public Sub Download(url as String)
Dim req As HttpWebRequest = System.Net.WebRequest.Create(url)
req.Method = "GET"
Dim resp As HttpWebResponse = req.GetResponse()
If resp.ContentType = "application/zip" Then
Console.Error.Write("The result is a zip file.")
Dim length As Int64 = resp.ContentLength
If length = -1 Then
Console.Error.WriteLine("... length unspecified")
length = 16 * 1024
Else
Console.Error.WriteLine("... has length {0}", length)
End If
Dim ms As New MemoryStream
CopyStream(resp.GetResponseStream(), ms) '' **see note below!!!!
'' list contents of the zip file
ms.Seek(0,SeekOrigin.Begin)
Using zip As ZipFile = ZipFile.Read (ms)
Dim e As ZipEntry
Console.Error.WriteLine("Entries:")
Console.Error.WriteLine(" {0,22} {1,10} {2,12}", _
"Name", "compressed", "uncompressed")
Console.Error.WriteLine("----------------------------------------------------")
For Each e In zip
Console.Error.WriteLine(" {0,22} {1,10} {2,12}", _
e.FileName, _
e.CompressedSize, _
e.UncompressedSize)
Next
End Using
Else
Console.Error.WriteLine("The result is Not a zip file.")
CopyStream(resp.GetResponseStream(), Console.OpenStandardOutput)
End If
End Sub
Private Shared Sub CopyStream(input As Stream, output As Stream)
Dim buffer(32768 - 1) As Byte
Dim n As Int32
Do
n = input.Read(buffer, 0, buffer.Length)
If n = 0 Then Exit Do
output.Write(buffer, 0, n)
Loop
End Sub
EDIT
Just one note - I would not advise using this code (this approach) if the Zip file is very large. How large is "very large"? Well that depends, of course. The code I suggested above downloads the file into a memory stream, which of course means the entire contents of the zip file are held in memory. If it is a 28kb zip file, then there's no problem. But if it is a 2gb zip file, then you may have a big problem.
In that case you will want to stream it to a temporary file on disk, not to a MemoryStream. I'll leave that as an exercise for the reader.
The above will work for "reasonably sized" zip files, where "reasonable" depends on your machine configuration and application scenario.