How to get the file's size using FtpWebResponse - vb.net

Trying to download file from a FTP to get download progress i have planned to implement backgroundWorker,the following code will display the download progress,speed,amount of kb downloading in the UI
Following is the code i wrote in backgroundWorker_doWork
'Creating the request and getting the response
Dim theResponse As FtpWebResponse
Dim theRequest As FtpWebRequest
Try
'Checks if the file exist
theRequest = WebRequest.Create(Me.txtFileName.Text)
theResponse = theRequest.GetResponse
Catch ex As Exception
MessageBox.Show("An error occurred while downloading file. Possible causes:" & ControlChars.CrLf & _
"1) File doesn't exist" & ControlChars.CrLf & _
"2) Remote server error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
Me.Invoke(cancelDelegate, True)
Exit Sub
End Try
Dim length As Long = theResponse.ContentLength 'Size of the response (in bytes)
Dim safedelegate As New ChangeTextsSafe(AddressOf ChangeTexts)
Me.Invoke(safedelegate, length, 0, 0, 0) 'Invoke the TreadsafeDelegate
Dim writeStream As New IO.FileStream(Me.whereToSave, IO.FileMode.Create)
'Replacement for Stream.Position (webResponse stream doesn't support seek)
Dim nRead As Integer
'To calculate the download speed
Dim speedtimer As New Stopwatch
Dim currentspeed As Double = -1
Dim readings As Integer = 0
Do
If BackgroundWorker1.CancellationPending Then 'If user abort download
Exit Do
End If
speedtimer.Start()
Dim readBytes(4095) As Byte
Dim bytesread As Integer = theResponse.GetResponseStream.Read(readBytes, 0, 4096)
nRead += bytesread
Dim percent As Short = (nRead * 100) / length
Me.Invoke(safedelegate, length, nRead, percent, currentspeed)
If bytesread = 0 Then Exit Do
writeStream.Write(readBytes, 0, bytesread)
speedtimer.Stop()
readings += 1
If readings >= 5 Then 'For increase precision, the speed it's calculated only every five cicles
currentspeed = 20480 / (speedtimer.ElapsedMilliseconds / 1000)
speedtimer.Reset()
readings = 0
End If
Loop
'Close the streams
theResponse.GetResponseStream.Close()
writeStream.Close()
If Me.BackgroundWorker1.CancellationPending Then
IO.File.Delete(Me.whereToSave)
Dim cancelDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
Me.Invoke(cancelDelegate, True)
Exit Sub
End If
Dim completeDelegate As New DownloadCompleteSafe(AddressOf DownloadComplete)
Me.Invoke(completeDelegate, False)
following is the error i got
Dim length As Long = theResponse.ContentLength getting -1
For example
ftp://username:mypassword#ftp.drivehq.com/masters/5/party/party.csv
above given is the ftp Url am passing to download file, here party.csv is the file to download
NOTE : the problem is when getting the file size of the file to download in my case the size of party,csv, Dim length As Long = theResponse.ContentLength. here theResponse.ContentLength getting -1 the actual size of the file is 420KB if i change
Dim length As Long =430080(420kb=430080bytes) the code will work

Found the following solution to get the exact method to find the file's size
Dim request As FtpWebRequest = DirectCast(WebRequest.Create(Me.txtFileName.Text), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.GetFileSize
Dim response As FtpWebResponse = DirectCast(request.GetResponse(), FtpWebResponse)
Dim fileSize As Long = response.ContentLength

Related

How can I make this recursive function more efficient?

I created this function to recursively copy an entire directory from an FTP server. It works just fine except that it is about 4 times slower than using FileZilla to do the same operation. It takes approximately 55 seconds to download the directory in FileZilla but it takes 229 seconds with this function. What can I do to make it download/run faster?
Private Sub CopyEntireDirectory(ByVal directory As String)
Dim localPath = localDirectory & formatPath(directory)
'creates directory in destination path
IO.Directory.CreateDirectory(localPath)
'Gets the directory details so I can separate folders from files
Dim fileList As ArrayList = Ftp.ListDirectoryDetails(directory, "")
For Each item In fileList
'checks if it's a folder or file: d=folder
If (item.ToString().StartsWith("d")) Then
'gets the directory from the details
Dim subDirectory As String = item.ToString().Substring(item.ToString().LastIndexOf(" ") + 1)
CopyEntireDirectory(directory & "/" & subDirectory)
Else
Dim remoteFilePath As String = directory & "/" & item.ToString().Substring(item.ToString().LastIndexOf(" ") + 1)
Dim destinationPath = localPath & "\" & item.ToString().Substring(item.ToString().LastIndexOf(" ") + 1)
'downloads file to destination directory
Ftp.DownLoadFile(remoteFilePath, destinationPath)
End If
Next
End Sub
Below is the download function that is taking up all the time.
Public Sub DownLoadFile(ByVal fromFilename As String, ByVal toFilename As String)
Dim files As ArrayList = Me.ListDirectory(fromFilename, "")
Dim request As FtpWebRequest = Me.CreateRequestObject(fromFilename)
request.Method = WebRequestMethods.Ftp.DownloadFile
Dim response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
If response.StatusCode <> FtpStatusCode.OpeningData AndAlso response.StatusCode <> FtpStatusCode.DataAlreadyOpen Then
Throw New ApplicationException(Me.BuildCustomFtpErrorMessage(request, response))
End If
Dim fromFilenameStream As Stream = response.GetResponseStream()
Dim toFilenameStream As FileStream = File.Create(toFilename)
Dim buffer(BLOCK_SIZE) As Byte
Dim bytesRead As Integer = fromFilenameStream.Read(buffer, 0, buffer.Length)
Do While bytesRead > 0
toFilenameStream.Write(buffer, 0, bytesRead)
Array.Clear(buffer, 0, buffer.Length)
bytesRead = fromFilenameStream.Read(buffer, 0, buffer.Length)
Loop
response.Close()
fromFilenameStream.Close()
toFilenameStream.Close()
End Sub
The slowness would obviously be within then FTP commands. Running your other code recursively would likely be able to run a million times per second because there is nothing to it.
The FTP download (whatever it is) should have the ability to define the size of the chunks is grabs. This will be key in your speed. It needs to be optimized based on your connection speed and file size. There is no RIGHT number for everyone.
EDIT
Based on the new code, the issue is in your BLOCK_SIZE which I assume is a constant. Play with the size of this to get your optimal speed.
HINT: This should be a multiple of 1024

get byte or image from Crypto Service Provider

I used This Code To Encrypt and Decrypt Data In my application
but the code use File Stream to do all work This is the code :
Dim bytKey As Byte()
Dim bytIV As Byte()
bytKey = CreateKey("mrbrashad1999")
bytIV = CreateIV("mrbrashad1999")
Try 'In case of errors.
'Setup file streams to handle input and output.
fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, _
FileAccess.Read)
fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, _
FileAccess.Write)
fsOutput.SetLength(0) 'make sure fsOutput is empty
'Declare variables for encrypt/decrypt process.
Dim bytBuffer(4096) As Byte 'holds a block of bytes for processing
Dim lngBytesProcessed As Long = 0 'running count of bytes processed
Dim lngFileLength As Long = fsInput.Length 'the input file's length
Dim intBytesInCurrentBlock As Integer 'current bytes being processed
Dim csCryptoStream As CryptoStream
'Declare your CryptoServiceProvider.
Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged
'Setup Progress Bar
'pbStatus.Value = 0
'pbStatus.Maximum = 100
'Determine if ecryption or decryption and setup CryptoStream.
Select Case Direction
Case CryptoAction.ActionEncrypt
csCryptoStream = New CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write)
Case CryptoAction.ActionDecrypt
csCryptoStream = New CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write)
End Select
'Use While to loop until all of the file is processed.
While lngBytesProcessed < lngFileLength
'Read file with the input filestream.
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)
'Write output file with the cryptostream.
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)
'Update lngBytesProcessed
lngBytesProcessed = lngBytesProcessed + CLng(intBytesInCurrentBlock)
'Update Progress Bar
'pbStatus.Value = CInt((lngBytesProcessed / lngFileLength) * 100)
End While
'Close FileStreams and CryptoStream.
csCryptoStream.Close()
fsInput.Close()
fsOutput.Close()
'Catch file not found error.
Catch When Err.Number = 53 'if file not found
MsgBox("Please check to make sure the path and filename" + _
"are correct and if the file exists.", _
MsgBoxStyle.Exclamation, "Invalid Path or Filename")
'Catch all other errors. And delete partial files.
Catch
fsInput.Close()
fsOutput.Close()
End Try
what i should do to get byte() or image From encrypted data in my file system direct to my application variable .
A CryptoStream simply sits on top of another Stream. When you Write to the CryptoStream, it takes the Byte array that you pass in, encrypts it and populates another array with the result, then it will Write that to the underlying Stream. Likewise, when you call Read it will call Read on the underlying Stream, decrypt it and then pass you the result. In your case you are using a FileStream but it can be any type of Stream at all, e.g. NetworkStream or GZipStream. If you want a temporary place to store binary data within your app then you can use a MemoryStream. The code to use the Stream is the same regardless of its type.

VB.NET FTP Downloaded file corrupt

I want to download all file that located on FTP site. I break into 2 operations. First is to get the list of all files in the directory. Then I proceed to second which download each file. But unfortunately, the downloaded file is corrupt. Worst over, it affect the file on FTP folder. Both folder contains corrupt file. From a viewing thumbnails image to default image thumbnails. How this happen and to overcome this? Below are my code; full code class. I provide as reference and guide to do a correct way :)
Private strTargetPath As String
Private strDestPath As String
Private Sub frmLoader_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
objSQL = New clsSQL
If objSQL.SQLGetAllData Then 'Get data from SQL and insert into an arraylist
strTargetPath = "ftp://192.168.1.120/image/"
strDestPath = "D:\Application\FTPImg\"
ListFileFromFTP()
End If
Catch ex As Exception
strErrMsg = "Oops! Something is wrong with loading login form."
MessageBox.Show(strErrMsg & vbCrLf & "ExMsg: " & ex.Message, "Error message!", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub ListFileFromFTP()
Dim arrFile As ArrayList
Dim strPath As String
Try
Dim reqFTP As FtpWebRequest
reqFTP = FtpWebRequest.Create(New Uri(strTargetPath))
reqFTP.UseBinary = True
reqFTP.Credentials = New NetworkCredential("user", "user123")
reqFTP.Method = WebRequestMethods.Ftp.ListDirectory
reqFTP.Proxy = Nothing
reqFTP.KeepAlive = False
reqFTP.UsePassive = False
Dim response As FtpWebResponse = DirectCast(reqFTP.GetResponse(), FtpWebResponse)
Dim sr As StreamReader
sr = New StreamReader(reqFTP.GetResponse().GetResponseStream())
Dim FileListing As String = sr.ReadLine
arrFile = New ArrayList
While FileListing <> Nothing
strPath = strTargetPath & FileListing
arrFile.Add(strPath)
FileListing = sr.ReadLine
End While
sr.Close()
sr = Nothing
reqFTP = Nothing
response.Close()
For i = 0 To (arrFile.Count - 1)
DownloadImage(arrFile.Item(i))
Next
Catch ex As Exception
strErrMsg = "Oops! Something is wrong with ListFileFromFTP."
MessageBox.Show(strErrMsg & vbCrLf & "ExMsg: " & ex.Message, "Error message!", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Public Function DownloadImage(ByVal strName As String) As String
Dim ftp_request As FtpWebRequest = Nothing
Dim ftpStream As Stream = Nothing
Dim strOldName As String
Dim strNewName As String
Dim withoutextension As String
Dim extension As String
Try
strOldName = strTargetPath & strName
withoutextension = Path.GetFileNameWithoutExtension(strOldName)
extension = Path.GetExtension(strOldName)
strNewName = strDestPath & withoutextension & extension
ftp_request = CType(System.Net.FtpWebRequest.Create(strName), System.Net.FtpWebRequest)
ftp_request.Method = System.Net.WebRequestMethods.Ftp.UploadFile
ftp_request.Credentials = New System.Net.NetworkCredential("user", "user123")
ftp_request.UseBinary = True
ftp_request.KeepAlive = False
ftp_request.Proxy = Nothing
Dim response As FtpWebResponse = DirectCast(ftp_request.GetResponse(), FtpWebResponse)
Dim responseStream As IO.Stream = response.GetResponseStream
Dim fs As New IO.FileStream(strNewName, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Do
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
Loop Until read = 0
responseStream.Close()
fs.Flush()
fs.Close()
responseStream.Close()
response.Close()
Catch ex As WebException
Dim response As FtpWebResponse = ex.Response
If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
MsgBox(response.StatusDescription)
Return String.Empty
Else
MsgBox(response.StatusDescription)
End If
End Try
End Function
For download file, this is the right code that succeed:
Private Sub Download(ByVal strFTPPath As String)
Dim reqFTP As FtpWebRequest = Nothing
Dim ftpStream As Stream = Nothing
Try
Dim outputStream As New FileStream(strDestPath & strImgName, FileMode.Create)
reqFTP = DirectCast(FtpWebRequest.Create(New Uri(strFTPPath)), FtpWebRequest)
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile
reqFTP.UseBinary = True
reqFTP.Credentials = New NetworkCredential("user", "user123")
Dim response As FtpWebResponse = DirectCast(reqFTP.GetResponse(), FtpWebResponse)
ftpStream = response.GetResponseStream()
Dim cl As Long = response.ContentLength
Dim bufferSize As Integer = 2048
Dim readCount As Integer
Dim buffer As Byte() = New Byte(bufferSize - 1) {}
readCount = ftpStream.Read(buffer, 0, bufferSize)
While readCount > 0
outputStream.Write(buffer, 0, readCount)
readCount = ftpStream.Read(buffer, 0, bufferSize)
End While
ftpStream.Close()
outputStream.Close()
response.Close()
Catch ex As Exception
If ftpStream IsNot Nothing Then
ftpStream.Close()
ftpStream.Dispose()
End If
Throw New Exception(ex.Message.ToString())
End Try
End Sub
There is something strange in your code. You are closing the responseStream twice.
And you are using ftp request method uploadFile. But then downloading it.
Instead of using the ftp stuff use this instead. Its much more simple and your outsourcing the buffers and streams to microsoft, which should be less buggy than us.
Dim webClient = new WebClient()
webClient.Credentials = new NetworkCredential("user", "user123")
dim response = webClient.UploadFile("ftp://MyFtpAddress","c:\myfile.jpg")
dim sResponse = System.Text.Encoding.Default.GetString(response)

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")

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.