Compression to stream - vb.net

I'm attempting to compress a file to stream which is sent over wcf and decompressed. However with the following code the I'm get not a valid exe when attempting to execute the decompressed exe. Any decompressed exe is around 211-212 bytes lower that the original.
Sub Main()
Dim strm As Stream = CompressToStream("c:\rje\Launcher.exe")
DecompressToFile(strm)
End Sub
Compression Routine
Private Function CompressToStream(ByVal strFullFilename As String) As Stream
If File.Exists(strFullFilename) Then
Dim uncompressedfile As New MemoryStream(File.ReadAllBytes(strFullFilename))
Dim compressedStream As New MemoryStream
Dim compressionStream As New GZipStream(compressedStream, CompressionMode.Compress)
uncompressedfile.CopyToStream(compressionStream)
compressionStream.Flush()
compressedStream.Position = 0
Return compressedStream
End If
Return Nothing
End Function
Extension method to copy streams as using .net3.5
<System.Runtime.CompilerServices.Extension()> _
Private Sub CopyToStream(ByVal input As Stream, ByRef output As Stream)
Dim Buffer(4096) As Byte
Dim numRead As Integer = input.Read(Buffer, 0, Buffer.Length)
Do While numRead <> 0
output.Write(Buffer, 0, numRead)
numRead = input.Read(Buffer, 0, Buffer.Length)
Loop
End Sub
Finally Decompression
Private Sub DecompressToFile(ByVal strmDownload As Stream)
Dim spath As String = "c:\rje\text.exe"
Using outFile As FileStream = File.Create(spath)
Using Decompress As GZipStream = New GZipStream(strmDownload, CompressionMode.Decompress)
' Copy the compressed file into the decompression stream.
Dim buffer(4096) As Byte
Dim numRead As Integer = Decompress.Read(buffer, 0, buffer.Length)
Do While numRead <> 0
outFile.Write(buffer, 0, numRead)
numRead = Decompress.Read(buffer, 0, buffer.Length)
Loop
End Using
outFile.Close()
End Using
End Sub
If someone could point out where I'm going wrong that would be great.

The error was with CompressToStream, amending as follows functions correctly
Private Function CompressToStream(ByVal strFullFilename As String) As Stream
If File.Exists(strFullFilename) Then
Dim compressedStream As New MemoryStream()
Using uncompressedfile As New MemoryStream(File.ReadAllBytes(strFullFilename))
Using compressionStream As New GZipStream(compressedStream, CompressionMode.Compress, True)
uncompressedfile.CopyToStream(compressionStream)
End Using
End Using
compressedStream.Seek(0, SeekOrigin.Begin)
Return compressedStream
End If
Return Nothing
End Function
I still don't have an answer as to why I shouldn't use File.Exists()?

Here are adapted Compress()/Decompress() methods from the sample in the link I posted in my comment:
Private Function Compress(ByVal strFullFilename As FileInfo) As Stream
' Get the stream of the source file.
Dim fi as New FileInfo(strFullFilename)
Dim result As New MemoryStream()
Using inFile As FileStream = fi.OpenRead()
' Compressing:
' Prevent compressing hidden and already compressed files.
If (File.GetAttributes(fi.FullName) And FileAttributes.Hidden) _
<> FileAttributes.Hidden And fi.Extension <> ".gz" Then
' Create the compressed file.
Using Compress As GZipStream = New GZipStream(result, CompressionMode.Compress)
' Copy the source file into the compression stream.
Dim buffer As Byte() = New Byte(4096) {}
Dim numRead As Integer = inFile.Read(buffer, 0, buffer.Length)
Do While numRead <> 0
Compress.Write(buffer, 0, numRead)
numRead = inFile.Read(buffer, 0, buffer.Length)
Loop
'Console.WriteLine("Compressed {0} from {1} to {2} bytes.", fi.Name, fi.Length.ToString(), result.Length.ToString())
End Using
End If
End Using
Return result
End Sub
' Method to decompress.
Private Sub Decompress(ByVal strmDownload As Stream, ByVal resultFileName As String)
' Create the decompressed file.
Using outFile As FileStream = File.Create(resultFileName)
Using Decomp As GZipStream = New GZipStream(strmDownload, CompressionMode.Decompress)
' Copy the compressed file into the decompression stream.
Dim buffer As Byte() = New Byte(4096) {}
Dim numRead As Integer = Decompress.Read(buffer, 0, buffer.Length)
Do While numRead <> 0
outFile.Write(buffer, 0, numRead)
numRead = Decomp.Read(buffer, 0, buffer.Length)
Loop
'Console.WriteLine("Decompressed: {0}", fi.Name)
End Using
End Using
End Using
End Sub

Related

How to compare bytes of array in stream which i have write it before?

I want to check if my edited stream have my bytes but the result is always failed I just can't find the wrong with my function
Public Function passbyte(ByVal filename As String, ByVal pass As String)
As Boolean
Dim passarray(0 to 2) As Byte
Dim realarray(0 To 2) As Byte
Dim result = False
Dim pos As Integer
pos = 0
If IO.File.Exists(filename) Then
Using Stream As New FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
Stream.Seek(pos, SeekOrigin.Begin)
passarray = System.Text.Encoding.ASCII.GetBytes(pass)
Stream.Write(passarray, 0, 3)
Stream.Read(realarray, 0, 3)
If realarray(0) = passarray(0) and realarray(1) = passarray(1) and realarray(2) = passarray(2) Then
result = True
MsgBox("Success")
Else
result = False
MsgBox("Failed")
End If
stream.close()
End Using
End If
Return result
End Function
Can't you do this without the loops?
If pass = My.Computer.FileSystem.ReadAllText(filename) Then

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!

FTP upload ProgressBar in VB.NET

I'm coding an application that uploads a file to a remote FTP server. This is my code that already works.
clsrequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
Dim bFile() As Byte = System.IO.File.ReadAllBytes(rutaorigen)
Dim clsStream As System.IO.Stream = clsrequest.GetRequestStream()
clsStream.Write(bFile, 0, bFile.Length)
clsStream.Close()
clsStream.Dispose()
Now I want to show the progress in a ProgressBar in VB.NET.
Files are not too big (10 MB max).
I've already tried an example that I found here, but it didn't work.
I hope you can help me. Thanks!
Simple progress on console:
Dim request As WebRequest = WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip")
request.Credentials = New NetworkCredential("username", "password")
request.Method = WebRequestMethods.Ftp.UploadFile
Using fileStream As Stream = File.OpenRead("C:\local\path\file.zip"),
ftpStream As Stream = request.GetRequestStream()
Dim buffer As Byte() = New Byte(10240 - 1) {}
Dim read As Integer
Do
read = fileStream.Read(buffer, 0, buffer.Length)
If read > 0 Then
ftpStream.Write(buffer, 0, read)
Console.WriteLine("Uploaded {0} bytes", fileStream.Position)
End If
Loop While read > 0
End Using
WinForms GUI progress:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Run Upload on background thread
Task.Run((Sub() Upload()))
End Sub
Sub Upload()
Dim request As WebRequest =
WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip")
request.Credentials = New NetworkCredential("username", "password")
request.Method = WebRequestMethods.Ftp.UploadFile
Using fileStream As Stream = File.OpenRead("C:\local\path\file.zip"),
ftpStream As Stream = request.GetRequestStream()
ProgressBar1.Invoke(Sub() ProgressBar1.Maximum = fileStream.Length)
Dim buffer As Byte() = New Byte(10240 - 1) {}
Dim read As Integer
Do
read = fileStream.Read(buffer, 0, buffer.Length)
If read > 0 Then
ftpStream.Write(buffer, 0, read)
ProgressBar1.Invoke(Sub() ProgressBar1.Value = fileStream.Position)
End If
Loop While read > 0
End Using
End Sub
I got this from an example a long time ago. The code should be fairly easy to change for your needs.
Dim clsRequest As System.Net.FtpWebRequest = _
DirectCast(System.Net.WebRequest.Create(ServLabel.Text & TextBox1.Text), System.Net.FtpWebRequest)
clsRequest.Credentials = New System.Net.NetworkCredential(PassLabel.Text, UserLabel.Text)
clsRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
rfshTMR.Enabled = True
Dim File() As Byte = System.IO.File.ReadAllBytes(txtFile.Text)
Dim clsStream As System.IO.Stream = _
clsRequest.GetRequestStream()
clsStream.Write(File, 0, File.Length)
For offset As Integer = 0 To File.Length Step 1024
ToolStripProgressBar1.Value = CType(offset * ToolStripProgressBar1.Maximum / File.Length, Integer)
Dim chunkSize As Integer = File.Length - offset - 1
If chunkSize > 1024 Then chunkSize = 1024
clsStream.Write(File, offset, chunkSize)
ToolStripProgressBar1.Value = ToolStripProgressBar1.Maximum
Next
clsStream.Close()
clsStream.Dispose()
MsgBox("File Is Now In Database", MsgBoxStyle.OkOnly, "Upload Complete")

Read/Write binary files

I have this code which works well:
Public Function LoadBinaryFile(strFilename As String) As Byte()
Using fsSource As FileStream = New FileStream(strFilename, FileMode.Open, FileAccess.Read)
' Read the source file into a byte array.
Dim bytes() As Byte = New Byte((fsSource.Length) - 1) {}
Dim numBytesToRead As Integer = CType(fsSource.Length, Integer)
Dim numBytesRead As Integer = 0
'tsProgressBar.Minimum = 0
'tsProgressBar.Maximum = numBytesToRead
While (numBytesToRead > 0)
' Read may return anything from 0 to numBytesToRead.
Dim n As Integer = fsSource.Read(bytes, numBytesRead, _
numBytesToRead)
' Break when the end of the file is reached.
If (n = 0) Then
Exit While
End If
numBytesRead = (numBytesRead + n)
numBytesToRead = (numBytesToRead - n)
'tsProgressBar.Value = numBytesRead
End While
numBytesToRead = bytes.Length
Return bytes
End Using
End Function
And I have this code to save the file which also works well:
Public Function SaveBinaryFile(strFilename As String, bytesToWrite() As Byte) As Boolean
Using fsNew As FileStream = New FileStream(strFilename, FileMode.Create, FileAccess.Write)
fsNew.Write(bytesToWrite, 0, bytesToWrite.Length)
End Using
End Function
What I am after is some help to modify the SaveBinaryFile function to implement a progress bar.
Final:
OK, I have written the function myself. Here it is:
Public Function ReadBinaryFile(strFilename As String) As Byte()
Dim position As Integer = 0
Dim bufferSize As Integer = 4096
Dim bytes() As Byte
'frmMain.tsProgressBar.Value = 0
Using fsOpen As FileStream = New FileStream(strFilename, FileMode.Open)
redim bytes((fsOpen.Length) - 1)
Do
If (position + bufferSize) > fsOpen.Length Then
fsOpen.Read(bytes, position, fsOpen.Length - position)
Exit Do
Else
fsOpen.Read(bytes, position, bufferSize)
End If
'frmMain.tsProgressBar.Value = ((position / fsOpen.Length) * 100)
'frmMain.tsProgressBar.Refresh()
Application.DoEvents()
position += bufferSize
Loop
End Using
Return bytes
End Function
My.Computer.Filesystem.ReadAllBytes("filename") reads the entire file into a byte array.
My.Computer.Filesystem.WriteAllBytes("filename", bytes, false) writes it back.
I've never tried using the Async options on FileStream but there don't seem to be any event handlers.
I would break it down into a loop, you have the total amount of bytes to write so you could loop through writing 4k at a time, update your progress bar and continue the loop.
Public Sub SaveBinaryFile(strFilename As String, bytesToWrite() As Byte)
Dim position As Integer = 0
Using fsNew As FileStream = New FileStream(strFilename, FileMode.Create, FileAccess.Write)
Do
Dim intToCopy As Integer = Math.Min(4096, bytesToWrite.Length - position)
Dim buffer(intToCopy - 1) As Byte
Array.Copy(bytesToWrite, position, buffer, 0, intToCopy)
fsNew.Write(buffer, 0, buffer.Length)
ProgressBar1.Value = ((position / bytesToWrite.Length) * 100)
Application.DoEvents()
position += intToCopy
Loop While position < bytesToWrite.Length
End Using
End Sub
'Or, if you are reading a file from a URL, here is a way to read the file into an array of bytes.
Dim WebRequest As Net.HttpWebRequest = Net.WebRequest.Create("http://mypage.abc.com/myfolder/MyFileName.xls")
Using WBinReader As BinaryReader = New BinaryReader(WRequest.GetResponse.GetResponseStream)
Dim file_buffer() As Byte
'10000000 is an arbitrary number, but File_Buffer will have no more
'elements than they number of bytes in the URL's file.
file_buffer = WBinReader.ReadBytes(10000000)
file_bytes =UBound(buffer)+1
End Using
Brian Jasmer

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.