-->

DotNetZip download works in one site, not another

2019-09-17 01:03发布

问题:

EDIT - RESOLVED: the difference was that in the "main" case the download was initiated via a callback cycle, and in the "test" case it was initiated through a server side button click function. My guess is that the download request and the callback cycle interfered with each other, both stopping the download and causing the page to become inactive (as described below). When I rewired the download on the main page to start with a submit instead of a callback, it did initiate the download.

This is in VS2013 Ultimate, Win7Pro, VB.Net, websites (not projects),IISExpress.

I built a test site to develop functionality for creating OpenXML PPTX and XLSX memorystreams and zipping and downloading them using DotNetZip. Got it to work fine. I then merged all that code into my "main" site. Both sites are on the same machine; I can run the test site and the main site at the same time. The main site processing is somewhat more complicated, but only in terms of accessing and downloading more files.

However, the Zip and Download function (below) works fine in the test site, but the exact same code doesn't work in the main site (with or without the test site up and running).

There's an error trap (see below) around the Zip.Save function where the download occurs but no error shows up.

Same overall behavior in Chrome, Firefox and IE11.

One peculiarity that might be a clue is that when the main site download fails, the server side functionality "goes dead". Local JS functions work, but the app doesn't respond to callbacks. When I do an F5 on the browser it works again.

I did a refresh on the DotNetZip package in the main site. The Zip object appears to be working properly, because it generates an error on duplicate file names.

I thought it might be the download function as written, however, it works in the test site. Also, another piece of the main site does a non-zipped download of a memory stream (included as the second code block below) and that works fine.

I thought it might be the data. So I kludged the main site to access, convert to memorystream and download the same file that the is accessed and downloaded in the test site. Still the main site download doesn't work.

When I compare the watch values on the Zip object in the two sites, they look identical. The length of the wrkFS.ContentStream is identical in both cases. The file names are different, however, they are: Test_2EFVG1THK5.xlsx (main) 6-18_12-46-28_0.xlsx (test) which are both legal file names.

EDIT: I saved the zip file to disk from the main program, instead of trying to download it, using this:

                wrkFilePath = "D:\filepath\test.zip"
                wrkZip.Save(wrkFilePath)

And it worked fine. So that possibly isolates the problem to this statement

            wrkZip.Save(context.Response.OutputStream)

EDIT: Base on help I received here:

Convert DotNetZip ZipFile to byte array

I used this construct:

Dim ms as New MemoryStream
wrkZip.Save(ms)
wrkBytes = ms.ToArray()
context.Response.BinaryWrite(wrkByteAr)

to get around the ZipFile.Save(to context), and that didn't work either; no download, no error message, and page goes dead. However, at least I can now assume it's not a problem with the ZipFile.Save.

At this point I'm out of ways to diagnose the problem.

Any suggestions would be appreciated.

Here is the code that works in the test site but not in the main site.

    Public Sub ZipAndDownloadMemoryStreams(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
    Dim rtn As String = ""

    Try
        Dim wrkAr As ArrayList
        wrkAr = SC.ContentArrayForDownLoad
        If wrkAr.Count = 0 Then
            Dim wrkStop As Integer = 0
            Exit Sub
        End If

        Dim wrkFS As ZipDownloadContentPair
        Using wrkZip As New ZipFile
            '----- create zip, add memory stream----------
            For n As Integer = 0 To wrkAr.Count - 1
                wrkFS = wrkAr(n)
                wrkZip.AddEntry(wrkFS.FileName, wrkFS.ContentStream)
            Next

            context.Response.Clear()
            context.Response.ContentType = "application/force-download"
            context.Response.AddHeader( _
                "content-disposition", _
                "attachment; filename=" & "_XYZ_Export.zip")
            '---- save context (initiate download)-----
            wrkZip.Save(context.Response.OutputStream)
            wrkZip.Dispose()

        End Using

    Catch ex As Exception
        Dim exmsg As String = ex.Message
        Dim wrkStop As String = ""
    End Try
End Sub

Below is the non-zip download function that works fine in the main site. It might be possible to convert the Zip content to a byte array and try the download that way, however, I'm not sure how that would work.

(SEE EDIT NOTE ABOVE --- I implemented a version of the below, i.e. try to download byte array instead of directly ZipFile.Save(), however, it didn't help; still doesn't download, and still doesn't give any error message)

Public Sub DownloadEncryptedMemoryStream(ByVal context As HttpContext) _
    Implements IHttpHandler.ProcessRequest

    Dim wrkMemoryStream As New System.IO.MemoryStream()

    wrkMemoryStream = SC.ContentForDownload

    Dim wrkFileName As String = SC.ExportEncryptedFileName

    wrkMemoryStream.Position = 0
    Dim wrkBytesInStream As Byte() = New Byte(wrkMemoryStream.Length - 1) {}
    wrkMemoryStream.Read(wrkBytesInStream, 0, CInt(wrkMemoryStream.Length))

    Dim wrkStr As String = ""
    wrkStr = Encoding.UTF8.GetString(wrkMemoryStream.ToArray())


    wrkMemoryStream.Close()
    context.Response.Clear()
    context.Response.ContentType = "application/force-download"
    context.Response.AddHeader("content-disposition", "attachment; filename=" & wrkFileName)
    context.Response.BinaryWrite(wrkBytesInStream)
    wrkBytesInStream = Nothing
    context.Response.End()

回答1:

(Per the note now at the top of the question): The difference was that in the "main" case the download was initiated via a callback cycle, and in the "test" case it was initiated through a server side button click function. My guess is that the download request and the callback cycle interfered with each other, both stopping the download and causing the page to become inactive (as described below). When I rewired the download on the main page to start with a submit instead of a callback, it did initiate the download.