VB.NEt 无法 stream/download 压缩文件到客户端
VB.NEt cannot stream/download zip file to client
我有一个 PDF 字符串列表,其中包含“http://whatever.pdf”形式的字符串,需要创建它们的 zip 文件并将其作为下载流式传输到客户端。
奇怪的是,如果我创建了 zip(我正在使用 ZipOutputStream)并将文件写入磁盘,它就可以正常工作,我能够打开生成的 zip 文件并毫无问题地解压缩它,但是如果我流式传输(我需要做的)我得到一个相同大小的 zip 文件,但在尝试打开它时出错。
创建压缩包:
Private Function CreateZip(pdfPathList As List(Of String), fileRoot As String) As String
Response.Clear()
Response.BufferOutput = False
Response.ContentType = "application/zip"
Response.AddHeader("content-disposition", "attachment; filename=pdf.zip")
Dim pdfPathListLocal As List(Of String) = Utility.DownloadFilesFromList(pdfPathList, fileRoot)
Dim outputMemStream = Utility.GenerateZipOutpuStream(pdfPathListLocal)
Dim zipName As String = Guid.NewGuid.ToString() & ".zip"
outputMemStream.Position = 0
'Utility.WriteMemoryStreamToDisk(outputMemStream, fileRoot & "\" & zipName) => This line creates a valid zip file on disk, but I need to avoid it.
Response.AddHeader("Content-Length", outputMemStream.Length)
Response.Write(outputMemStream) => Writes the file ok in downloads, but apparently corrupted.
Return zipName
End Function
从列表下载文件:
Public Shared Function DownloadFilesFromList(pdfPathList As List(Of String), fileRoot As String) As List(Of String)
Dim pdfPathListLocal As New List(Of String)
Dim Client As WebClient = New WebClient()
For Each strFile In pdfPathList
Dim sFile As String = Path.GetFileName(strFile)
Dim localFile As String = fileRoot + "\" + sFile
Client.DownloadFile(strFile, localFile)
pdfPathListLocal.Add(localFile)
Next
Return pdfPathListLocal
End Function
生成 ZipOutpuStream:
Public Shared Function GenerateZipOutpuStream(pdfPathListLocal As List(Of String)) As MemoryStream
Dim outputMemStream = New MemoryStream()
Dim strmZipOutputStream = New ZipOutputStream(outputMemStream)
strmZipOutputStream.SetLevel(9)
Dim objCrc32 As New Crc32()
For Each strFile In pdfPathListLocal
Dim strmFile As FileStream = IO.File.OpenRead(strFile)
Dim abyBuffer(Convert.ToInt32(strmFile.Length - 1)) As Byte
strmFile.Read(abyBuffer, 0, abyBuffer.Length)
Dim sFile As String = Path.GetFileName(strFile)
Dim theEntry As ZipEntry = New ZipEntry(sFile)
theEntry.DateTime = DateTime.Now
theEntry.Size = strmFile.Length
strmFile.Close()
objCrc32.Reset()
objCrc32.Update(abyBuffer)
theEntry.Crc = objCrc32.Value
strmZipOutputStream.PutNextEntry(theEntry)
strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length)
'IO.File.Delete(strFile)
Next
strmZipOutputStream.Finish()
Return outputMemStream
End Function
WriteMemoryStreamToDisk:
Public Shared Sub WriteMemoryStreamToDisk(outputMemStream As MemoryStream, file As String)
Dim buffer As Byte() = outputMemStream.ToArray()
Dim ms As New MemoryStream(buffer)
Dim newFile As New FileStream(file, FileMode.Create, FileAccess.Write)
ms.WriteTo(newFile)
newFile.Close()
ms.Close()
End Sub
可能出了什么问题?有帮助吗?
在这种情况下,我通常首先做的是在文本查看器中打开“损坏的”文件,并确定假定的(文件类型)文件是否实际上是一个(文件类型)文件。事实往往并非如此。例如。查看常规 ZIP 存档时,前 2 个字符 必须 是“PK”,文件的其余部分是二进制“乱码”。 PDF 类似:前几个字符是“%PDF-(PDF 版本)”,例如"%PDF-1.7".
尤其是下载时,您最终可能会得到与预期不同的东西,例如右键单击文件 link -> “另存为”。事实证明,它不是直接 link 到文件,而是某种将实际文件推送到客户端的脚本。当您将 link“另存为”时,您得到的是脚本的 HTML 输出,而不是文件本身。
还有很多反恶意软件监控网络流量并用其他东西替换可疑文件。
您可能已经“沦为猎物”了。
好的,我终于找到了问题的根源,我会自己回答,希望对遇到同样问题的其他人有所帮助。
问题出在 aspx“UpdatePanel”的工作方式上,它执行部分回发,这与响应对象不兼容并阻止它正常工作。
解决方案是禁用导致问题的特定元素的部分回发,在我的例子中:
添加它会导致 aDownloadPdfs link 执行完整的回发,所有 Response 对象方法将按预期工作。
我有一个 PDF 字符串列表,其中包含“http://whatever.pdf”形式的字符串,需要创建它们的 zip 文件并将其作为下载流式传输到客户端。
奇怪的是,如果我创建了 zip(我正在使用 ZipOutputStream)并将文件写入磁盘,它就可以正常工作,我能够打开生成的 zip 文件并毫无问题地解压缩它,但是如果我流式传输(我需要做的)我得到一个相同大小的 zip 文件,但在尝试打开它时出错。
创建压缩包:
Private Function CreateZip(pdfPathList As List(Of String), fileRoot As String) As String
Response.Clear()
Response.BufferOutput = False
Response.ContentType = "application/zip"
Response.AddHeader("content-disposition", "attachment; filename=pdf.zip")
Dim pdfPathListLocal As List(Of String) = Utility.DownloadFilesFromList(pdfPathList, fileRoot)
Dim outputMemStream = Utility.GenerateZipOutpuStream(pdfPathListLocal)
Dim zipName As String = Guid.NewGuid.ToString() & ".zip"
outputMemStream.Position = 0
'Utility.WriteMemoryStreamToDisk(outputMemStream, fileRoot & "\" & zipName) => This line creates a valid zip file on disk, but I need to avoid it.
Response.AddHeader("Content-Length", outputMemStream.Length)
Response.Write(outputMemStream) => Writes the file ok in downloads, but apparently corrupted.
Return zipName
End Function
从列表下载文件:
Public Shared Function DownloadFilesFromList(pdfPathList As List(Of String), fileRoot As String) As List(Of String)
Dim pdfPathListLocal As New List(Of String)
Dim Client As WebClient = New WebClient()
For Each strFile In pdfPathList
Dim sFile As String = Path.GetFileName(strFile)
Dim localFile As String = fileRoot + "\" + sFile
Client.DownloadFile(strFile, localFile)
pdfPathListLocal.Add(localFile)
Next
Return pdfPathListLocal
End Function
生成 ZipOutpuStream:
Public Shared Function GenerateZipOutpuStream(pdfPathListLocal As List(Of String)) As MemoryStream
Dim outputMemStream = New MemoryStream()
Dim strmZipOutputStream = New ZipOutputStream(outputMemStream)
strmZipOutputStream.SetLevel(9)
Dim objCrc32 As New Crc32()
For Each strFile In pdfPathListLocal
Dim strmFile As FileStream = IO.File.OpenRead(strFile)
Dim abyBuffer(Convert.ToInt32(strmFile.Length - 1)) As Byte
strmFile.Read(abyBuffer, 0, abyBuffer.Length)
Dim sFile As String = Path.GetFileName(strFile)
Dim theEntry As ZipEntry = New ZipEntry(sFile)
theEntry.DateTime = DateTime.Now
theEntry.Size = strmFile.Length
strmFile.Close()
objCrc32.Reset()
objCrc32.Update(abyBuffer)
theEntry.Crc = objCrc32.Value
strmZipOutputStream.PutNextEntry(theEntry)
strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length)
'IO.File.Delete(strFile)
Next
strmZipOutputStream.Finish()
Return outputMemStream
End Function
WriteMemoryStreamToDisk:
Public Shared Sub WriteMemoryStreamToDisk(outputMemStream As MemoryStream, file As String)
Dim buffer As Byte() = outputMemStream.ToArray()
Dim ms As New MemoryStream(buffer)
Dim newFile As New FileStream(file, FileMode.Create, FileAccess.Write)
ms.WriteTo(newFile)
newFile.Close()
ms.Close()
End Sub
可能出了什么问题?有帮助吗?
在这种情况下,我通常首先做的是在文本查看器中打开“损坏的”文件,并确定假定的(文件类型)文件是否实际上是一个(文件类型)文件。事实往往并非如此。例如。查看常规 ZIP 存档时,前 2 个字符 必须 是“PK”,文件的其余部分是二进制“乱码”。 PDF 类似:前几个字符是“%PDF-(PDF 版本)”,例如"%PDF-1.7".
尤其是下载时,您最终可能会得到与预期不同的东西,例如右键单击文件 link -> “另存为”。事实证明,它不是直接 link 到文件,而是某种将实际文件推送到客户端的脚本。当您将 link“另存为”时,您得到的是脚本的 HTML 输出,而不是文件本身。
还有很多反恶意软件监控网络流量并用其他东西替换可疑文件。
您可能已经“沦为猎物”了。
好的,我终于找到了问题的根源,我会自己回答,希望对遇到同样问题的其他人有所帮助。
问题出在 aspx“UpdatePanel”的工作方式上,它执行部分回发,这与响应对象不兼容并阻止它正常工作。
解决方案是禁用导致问题的特定元素的部分回发,在我的例子中:
添加它会导致 aDownloadPdfs link 执行完整的回发,所有 Response 对象方法将按预期工作。