Home Forums .NET libraries Xceed Zip & Real-Time Zip for .NET WebProcess zip file in memory (ASP.Net)

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064
    #19567 |

    Hi !

    I have the following challenge :

    Some clients are uploading zipped files using the classic HttpPost command
    from a classic web client (IE).

    At the server side, I have a collection of all HttpPostedFile objects.
    I can easily obtain a stream from it : HttpPostedFile.InputStream

    I tried many techniques to process an archive in memory without success.

    In fact, I wanted to extract each files in the archive and apply
    some processing actions.

    Let’s imagine, for example, a client uploading an archive containing
    some image files (jpg) and you have to resize them to a fixed size.

    In the full process, I cannot use classic physical files on a filesystem,
    but only the memory !

    Thanks for any suggestion,
    MrBid.

    Imported from legacy forums. Posted by MrBid (had 5089 views)

    User (Old forums)
    Member
    Post count: 23064

    If you only need to read from that HttpPostedFile, then you can access your posted source zip files by using a StreamFile around the InputStream, then pass that StreamFile to a new ZipArchive.

    Then, you can open any ZippedFile inside that ZipArchive. Get the files using GetFiles, then call OpenRead on each of them and read your data in a byte array, for example. I beleive you can also create a new Image from a Stream.

    The real question is: Where do you want to save that image back? If it’s in the same zip file, then you can’t use InputStream. You’ll have to use the Filename and a DiskFile, making sure the ASP.NET user has permission to “discover” that path.

    Imported from legacy forums. Posted by Martin (had 511 views)

    User (Old forums)
    Member
    Post count: 23064

    Hi !

    In deed, in my real processing, I’m just checking and saving all files containing in the zipfile
    into a database.

    I tried this without success (zipstr is the InputStream of the HttpPostedFile) :

    Dim sf As New StreamFile(zipstr, “archive.zip”)
    Dim fs() As Xceed.FileSystem.AbstractFile
    Dim buf() As Byte
    Dim fname As String
    Dim ziparc As ZipArchive

    Dim mf As New MemoryFile(“RAM_FILE”, “archive.zip”)
    mf.Create()
    sf.Refresh()

    ziparc = New ZipArchive(mf)
    sf.CopyTo(ziparc, True)
    fs = ziparc.GetFiles(True, “*.xml”)

    But, the GetFiles method returns an empty array (fs) !
    There is a ZippedFile in the ZipArchive, but its length equal 813 only !!!

    MrBid.

    Imported from legacy forums. Posted by MrBid (had 317 views)

    User (Old forums)
    Member
    Post count: 23064

    You are copying a StreamFile named “archive.zip” into a ZipArchive named “RAM_FILE:\archive.zip”. Thus, your MemoryFile contains a zip file containing another zip file!!! q;-)

    First, you don’t actually need to work with a MemoryFile to access XML files in your zip file. Something like this should work:

    Dim sf As New StreamFile(zipstr, “archive.zip”)
    Dim ziparc As New ZipArchive(sf)
    Dim fs() As Xceed.FileSystem.AbstractFile

    fs = ziparc.GetFiles(True, “*.xml”)

    If you really want to work in memory, here’s the code:

    Dim sf As New StreamFile(zipstr, “archive.zip”)
    Dim mf As New MemoryFile(“RAM_FILE”, “archive.zip”)

    sf.CopyTo(mf, True)

    Dim ziparc As New ZipArchive(mf)

    Dim fs() As Xceed.FileSystem.AbstractFile
    fs = ziparc.GetFiles(True, “*.xml”)

    Imported from legacy forums. Posted by Martin (had 396 views)

    User (Old forums)
    Member
    Post count: 23064

    Thanks a lot for the tip !

    I receive no Exception, but a strange behaviour remains :

    After doing the OpenRead, I receive a stream, OK !

    I try to read the data :
    rci = wstr.Read(data, 0, fs(i).Size)

    and if, for example, fs(i).Size equals 90000 (=> the size of the uncompressed file),
    the Read method returns only a part of the full size !!!!

    Let’s say about 60000.

    If I execute the Read method a second time, I receive the remaining
    30000 bytes !!!!!!!!!!!

    Something is wrong ????!!!!!!!

    MrBid.

    Imported from legacy forums. Posted by MrBid (had 252 views)

    User (Old forums)
    Member
    Post count: 23064

    Yup, per the nature of any Stream-derived class, the Read method is <b>never</b> garanteed to return the number of bytes asked for. You must loop on it until you get the number of bytes you want.

    Excerpt from MSDN under System.IO.Stream.Read:
    <i><b>Return Value</b>: The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.</i>

    A loop may look like this:

    Dim toRead As Long = fs(i).Size
    Dim offset As Long = 0
    Dim data() as Byte = New Byte(toRead)
    Dim read As Integer

    Do While toRead > 0
    read = wstr.Read(data, offset, toRead)

    If read = 0 Then
    Throw New Exception(“Premature end of file”)
    End If

    ‘ Can we do that in VB.NET???
    toRead -= read
    offset += read
    Loop

    (I wrote that without testing, pardon possible mistakes!)

    Imported from legacy forums. Posted by Martin (had 369 views)

    User (Old forums)
    Member
    Post count: 23064

    Again,

    Thanks a lot.

    Now, that works fine !

    It can be useful to put an example outlining this topic (WebProcess Zip file in mem) in the FAQ.

    Bye,
    MrBid.

    PS: the full code of the function is here :

    Public Structure FileIn
    Dim data() As Byte
    Dim isCompressed As Boolean
    Dim optFilename As String
    Dim optSize As Long
    End Structure

    Public Structure ReturnInfo
    Dim retvalue As Object
    Dim rethicode As Long
    Dim retlocode As Long
    Dim retdesc As String
    Dim retex As Exception
    End Structure

    Public Function ExtractZipStream(ByRef zipstr As Stream, ByRef ddout() As FileIn) As RInfo
    Dim fs() As Xceed.FileSystem.AbstractFile
    Dim wstr As Stream
    Dim buf() As Byte
    Dim fname As String
    Dim rti As New RInfo
    Dim ios As MemoryStream
    Dim ziparc As ZipArchive

    Try
    Dim sf As New StreamFile(zipstr, “archive.zip”)

    Dim mf As New MemoryFile(“RAM_FILE”, “archive.zip”)
    sf.CopyTo(mf, True)

    ziparc = New ZipArchive(mf)

    fs = ziparc.GetFiles(True, “*.xml”)

    Dim i As Integer
    Dim rci As Integer
    ReDim ddout(fs.Length – 1)

    Dim data() As Byte
    For i = 0 To fs.Length – 1
    fname = fs(i).Name
    wstr = fs(i).OpenRead()
    ReDim data(fs(i).Size – 1)

    Dim off As Integer = 0
    rci = wstr.Read(data, 0, fs(i).Size)

    If rci = 0 Then
    Throw New Exception(“Premature end of file”)
    End If

    While rci <> 0
    off = off + rci
    rci = wstr.Read(data, off, fs(i).Size – off)
    End While

    wstr.Close()

    ddout(i).data = data
    ddout(i).isCompressed = False
    ddout(i).optFilename = fname
    ddout(i).optSize = data.Length
    Next

    rti.rethicode = 1
    rti.retlocode = 0
    rti.retdesc = “”

    ExtractZipStream = rti
    Catch ex As Exception
    rti.rethicode = -1
    rti.retlocode = 0
    rti.retdesc = ex.Message
    rti.retex = ex
    ExtractZipStream = rti
    End Try
    End Function

    Imported from legacy forums. Posted by MrBid (had 6090 views)

Viewing 7 posts - 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.