VB.NET - 在内存中下载 zip 并将文件从内存中提取到磁盘

标签 vb.net httpwebresponse dotnetzip

尽管找到了示例,但我在这方面遇到了一些麻烦。我认为这可能是编码问题,但我不确定。我正在尝试从使用 cookie 的 https 服务器以编程方式下载文件(因此我使用的是 httpwebrequest)。我正在调试打印要检查的流的容量,但输出 [原始] 文件看起来不同。已尝试其他编码无济于事。

代码:

    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

所以我下载了正确大小的文件,但 dotnetzip 无法识别它,并且复制出来的文件是不完整/无效的 zip。我今天大部分时间都花在这上面了,现在准备放弃了。

最佳答案

我认为答案将是分解问题,并可能更改代码中的几个方面。

例如,让我们摆脱将响应流转换为字符串的过程:

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

接下来,还有一种更简单的方法可以将内存流的内容输出到文件中。考虑你的代码
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

可以替换为
Using filestrm As FileStream = New FileStream("c:\temp\debug.zip", FileMode.Create)
    memstream.WriteTo(filestrm)
End Using

这消除了将您的内存流传输到另一个字节数组,然后将字节数组下推到流中的需要,而实际上内存流可以将数据直接传输到文件(通过文件流)保存中间人缓冲区。

我承认我没有使用过您正在使用的 Zip/压缩库,但是通过上述修改,您已经删除了流、字节数组、字符串等之间不必要的传输,并希望消除您遇到的编码问题。

尝试一下,让我们知道您的进展情况。考虑尝试打开您保存的文件(“C:\temp\debug.zip”)以查看它是否被列为损坏。如果没有,那么您至少知道代码中的内容,它可以正常工作。

关于VB.NET - 在内存中下载 zip 并将文件从内存中提取到磁盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6613123/

相关文章:

c# - 如何将 WebResponse.GetResponseStream 返回值转换成字符串?

c# - XML 文档 (1,2) 中存在错误,System.InvalidOperationException : <AuthorizationResult xlms :""> was not expected

c# - 解压后无法删除 zip 文件

sql - 使用 ADO .NET 调用 SQL 函数

将以下代码从 C 转换为 VB.NET

.net - 如何使用Case感测参数

asp.net-mvc - MVC4 中的 VB 强类型模型访问

c# - 尝试使用 HttpWebRequest 获取身份验证 cookie

c# - BackgroundWorker 调用目标抛出的异常

c# - 从流创建 Zip 文件并下载