Compressed SQL doc opens with .NET FileStream as a page of squares

Traitée Compressed SQL doc opens with .NET FileStream as a page of squares

  • vendredi 9 mars 2012 22:01
     
     
     

    We have some documents (.doc) that were saved into a SQL database as compressed images.

    I wrote a vb.net program that can view the documents.  It uses a reader and decompresses the sql blob to an outputStream and displays the document after a Response.Flush.  We sent the code and databases to another group to host this website themselves. They can run the website but when they view the documents the documents open with a page full of small squares.  I believe the data is not getting decompressed.  Their SQL server has a 64 bit Operating System and we have a 32 bit Operating System.  Can a compressed document stored in a 32 bit server be successfully opened in a 64 bit server?  We have the same version of Word, .Net Framework and the exact same data and code.  Any help, or suggestions would be greatly appreciated!  


    • Modifié mpls_bren vendredi 9 mars 2012 22:08
    •  

Toutes les réponses

  • lundi 12 mars 2012 07:52
    Modérateur
     
     

    Hi Mpls_bren,

    Welcome to the MSDN forum.

    The DOC format varies among Microsoft Office Word Formats. It’s not related to your OS version. So I think there may be something wrong with the compressing and decompressing.  I’d appreciate it if you could provide detailed information about the codes of compressing and decompressing.

    Have a nice day!


    Shanks Zen
    MSDN Community Support | Feedback to us

  • lundi 12 mars 2012 07:53
     
     

    The blob format is not related to the internal processor type of the server.

    However, if an end user sees square blocks, it has almost forever to do with the way the encoding has done related to the used code page or format. 

    See the top of this page for better understanding and the rest for more knowledge in depth.

    http://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.100).aspx

    This can also happen if a certain code page is not available.

    Success
    Cor


  • mardi 13 mars 2012 17:53
     
     
    Thank you both for the information.  I will try to gather the code to post it and will read the link provided above.  I guess I'm still confused because the documents decompress just fine for everyone here but not for the people we sent the code to and I don't have access to their system.  I know it's hard to help me unless I post the code so I will get that soon.  We are using zlibwapi.dll for the decompression and I believe that is how the documents were compressed originally as well. 
  • mardi 13 mars 2012 20:13
     
     

    Here is the code that decompresses and opens the .doc documents.  I have included the first part here because it was too large to include all of it.  

    [code language=VB]

     

    Private Sub SetupView(ByVal textDocID As Object, ByVal textOriginName As Object, ByVal textImaged As Object, ByVal textOrd As Object)

            'textDocID is the document id from the database

            'textOriginName is the app the doc originated from so I know the table to get the images from

            'textImaged is a flag from a table

            'textORD is the order number

            Dim viewReader As Data.SqlClient.SqlDataReader

            Dim strDocType As String

            Dim textSite As String

            Dim documentView As New DocumentGetByORDocumentRID()

            documentView.ORDocumentRID = textDocID

                documentView.ConnectionString = ConfigurationManager.ConnectionStrings("myConnectionString").ConnectionString

                documentView.ORDataApp = "myDatabase"

                documentView.ORStoredProc = "[dbo].[usp_Document_GetByORDocumentRID]"

                viewReader = documentView.ExecuteReader()

               

    Try

                    If (Object.Equals(documentView.ReturnValue, SqlInt32.Null) = False) Then

                        '*************************************************

                        'Get document properties data

                        '*************************************************

                        While viewReader.Read()

                            Dim contentType As String = viewReader("DocumentContentType")

                            Select Case Trim(contentType)

                                Case ".DOC"

                                    strDocType = "application/msword"

                                Case ".XML"

                                    strDocType = "application/xml"

                                Case ".PDF"

                                    strDocType = "application/pdf"

                                Case ".RTF"

                                    strDocType = "application/rtf"

                                Case ".ZIP"

                                    strDocType = "application/zip"

                                Case ".TIF", ".TIFF"

                                    strDocType = "image/tif"

                                Case ".TXT"

                                    strDocType = "application/octet-stream"

                                Case Else

                                    strDocType = "application/octet-stream"

                            End Select

                            'Instantiate the new object here, deallocate it

                            'When the form closes

                            objZLib = New clszlib

                            'Uncompress any text that is in the compression buffer

                            Dim intResult As Integer 'result from function call

                            Dim DocumentData() As Byte = CType(viewReader("Document"), Byte())

                            objZLib.m_arbytCompressionBuffer = DocumentData

                            objZLib.lngOriginalSize = viewReader("LENGTH")

                            'Check to make sure there is something in the buffer

                            If UBound(objZLib.m_arbytCompressionBuffer) > 0 Then

                                'Check to make sure that the original size of

                                'The uncompressed data is still held

                                If objZLib.lngOriginalSize > 0 Then

                                    'Decompress the buffer which is holding the compressed data

                                    Try

                                        intResult = objZLib.intDeCompressByteArray(objZLib.m_arbytCompressionBuffer)

                                    Catch ex As Exception

                                        ex.Message.ToString()

                                    End Try

                                    Response.Buffer = True

                                    'Opens in WORD which is not controlled by web, but by word.

                                    Response.AddHeader("content-disposition", "attachment;filename=" & viewReader("DocumentName"))

                                    Response.AddHeader("Content-Length", viewReader("Length"))

                                    Response.ContentType = strDocType

                                    Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))

                                    Response.Cache.SetCacheability(HttpCacheability.Public)

                                    Response.Cache.SetSlidingExpiration(True)

                                    Response.OutputStream.Write(CType(objZLib.m_arbytDeCompressionBuffer, Byte()), 0, CType(viewReader("Length"), Integer))

                                Else

                                    Response.Write("The file size is zero")

                                End If

                                Response.Flush()

                                Response.Close()

                            End If

                            'Deallocate the zlib object that was instantiated

                            'When the form was loaded

                            objZLib = Nothing

                           

                        End While

                        viewReader.Close()

                    End If

                Catch ex As Exception

                    Throw New ApplicationException("Error in page:  ViewDocs.vb  Module: Execute() As Collection")

                Finally

                    viewReader.Close()

                End Try

        End Sub

    [/code]


    • Modifié mpls_bren mardi 13 mars 2012 20:17
    •  
  • mardi 13 mars 2012 20:36
     
     

    This is the zlib.dll wrapper

    [code language=VB]

     

    '********************************************************************************

    'general purpose zlib.dll wrapper for compressing text, files, byte arrays, etc.

    '

    'December 12, 2004

    '

    'MS VB.NET 2003 (v7.1.3088), option explicit=on, option strict=on '

    'Kevin Pisarsky (http://www.pisarsky.com) (kevin@pisarsky.com) '

    'for usage see the demo application that should have been packed with this code '

    '********************************************************************************

    Imports System

    Imports System.Data

    Imports System.Data.SqlTypes

    Imports System.IO

    Imports System.Runtime.InteropServices

    Namespace myName.my.Utilities

        Public Class clszlib

            'the version of zlib used is zlibwapi.dll, v1.2.2.0, which was downloaded from the

            'official zlib page at http://www.gzip.org/zlib/

            '

            'this dll is the one compiled for windows9x/nt/2000/xp usage and is win32 compatible.

            'The dll was used without compiling from source, and without any modifications.

            '

            'class level constants

            Public Const Z_NO_FLUSH As Integer = 0

            'partial flush deprecated, use Z_SYNC_FLUSH instead

            Public Const Z_PARTIAL_FLUSH As Integer = 1

            Public Const Z_SYNC_FLUSH As Integer = 2

            Public Const Z_FULL_FLUSH As Integer = 3

            Public Const Z_FINISH As Integer = 4

            'allowed flush values ; see deflate() for details */

            Public Const Z_OK As Integer = 0

            Public Const Z_STREAM_END As Integer = 1

            Public Const Z_NEED_DICT As Integer = 2

            Public Const Z_ERRNO As Integer = -1

            Public Const Z_STREAM_ERROR As Integer = -2

            Public Const Z_DATA_ERROR As Integer = -3

            Public Const Z_MEM_ERROR As Integer = -4

            Public Const Z_BUF_ERROR As Integer = -5

            Public Const Z_VERSION_ERROR As Integer = -6

            'return codes for the compression/decompression functions. Negative

            'values are errors, positive values are used for special but normal events.

            Public Const Z_NO_COMPRESSION As Integer = 0

            Public Const Z_BEST_SPEED As Integer = 1

            Public Const Z_BEST_COMPRESSION As Integer = 9

            Public Const Z_DEFAULT_COMPRESSION As Integer = -1

            'compression levels

            Public Const Z_FILTERED As Integer = 1

            Public Const Z_HUFFMAN_ONLY As Integer = 2

            Public Const Z_DEFAULT_STRATEGY As Integer = 0

            'compression strategy

            Public Const Z_BINARY As Integer = 0

            Public Const Z_ASCII As Integer = 1

            Public Const Z_UNKNOWN As Integer = 2

            'possible values of the data_type field

            Public Const Z_DEFLATED As Integer = 8

            'the deflate compression method (the only one supported in this version)

            'for initializing zalloc, zfree, opaque

            Public Const Z_NULL As Integer = 0

            'class level variables

            'this is the file handle type

            Private gzFile As Long

            'this is the buffer used by intCompressByteArray to store

            'an array of compressed bytes - it is public so that the calling

            'application can have access to it if necessary

            Public m_arbytCompressionBuffer As Byte()

            'this is the buffer used by intDeCompressByteArray to store

            'an array of decompressed bytes - it is public so that the calling

            'application can have access to it if necessary

            Public m_arbytDeCompressionBuffer As Byte()

            'the original size of the data being compressed, whether it is

            'a buffer, file size or whatever. this number is set when you compress

            'something, and used when you uncompress it

            Private m_lngOriginalSize As Long

            'this is the zlib function for compressing a byte array

            <DllImport("zlibwapi.dll", EntryPoint:="compress")> Private Shared Function CompressByteArray(ByVal dest As Byte(), ByRef destLen As Integer, ByVal src As Byte(), ByVal srcLen As Integer) As Integer

                'leave function empty - DLLImport attribute forwards calls to CompressByteArray to compress in zlib.dLL

            End Function

            'this is the zlib function for decompressing a byte array

            'Private Declare Function uncompress Lib "zlibwapi.dll" (ByVal dest As Byte(), ByRef destLen As Integer, ByVal src As Byte(), ByVal srcLen As Integer) As Integer

            <DllImport("zlibwapi.dll", EntryPoint:="uncompress")> Private Shared Function UncompressByteArray(ByVal dest As Byte(), ByRef destLen As Integer, ByVal src As Byte(), ByVal srcLen As Integer) As Integer

                'leave function empty - DLLImport attribute forwards calls to UnCompressByteArray to Uncompress in zlib.dLL

            End Function

            'zlib function for opening a file for writing

            <DllImport("zlibwapi.dll", EntryPoint:="gzopen")> Private Shared Function OpenWrite(ByVal strPath As String, ByVal strMode As String) As Long

                'leave empty

            End Function

            Public Property lngOriginalSize() As Long

                'this property holds the original size of data being compressed. it is necessary to

                'keep the original size of the data in order to uncompress it. whenever possible this

                'property is automatically set by the compression procedures; it may be necessary for

                'your application to set the property if the application is shut down or this class is

                'deallocated between compression and decompression procedures.

                Get

                    lngOriginalSize = m_lngOriginalSize

                End Get

                Set(ByVal lngValue As Long)

                    m_lngOriginalSize = lngValue

                End Set

            End Property

            'compress a byte array into a buffer, return value:

            ' the size of the compressed buffer if the operation was successful

            ' return -1 if the operation was unsuccessful but no specific error is provided

            ' return -4 if there was not enough memory to complete the operation

            ' return -5 if there was not enough room in the output buffer (intBufferSize not large enough)

            Public Function intCompressByteArray(ByRef arbytData() As Byte, Optional ByRef TempBuffer() As Byte = Nothing) As Integer

                'parameters: arbytData is a one dimensional array of bytes

                Dim intResult As Integer 'result of the call to zlibwapi.dll

                Dim intBufferSize As Integer 'size of the uncompressed byte array being passed in

                'set the original size of the data, this is used when the data is to be

                'uncompressed

                m_lngOriginalSize = UBound(arbytData) + 1

                'set the size of the buffer for the data to be compressed into; the buffer size

                'must be at least 0.1% larger than the uncompressed data, plus 12 bytes. after

                'the function is successful, intBufferSize will be the actual size of the

                'compressed buffer

                intBufferSize = CInt(m_lngOriginalSize)

                intBufferSize = CInt(intBufferSize + (intBufferSize * 0.015) + 12)

                'redimension the compression buffer to the correct size

                'for this operation

                ReDim m_arbytCompressionBuffer(intBufferSize)

                'call the zlibwapi.dll function "compress" to actually compress the bytes

                intResult = CompressByteArray(m_arbytCompressionBuffer, intBufferSize, arbytData, UBound(arbytData) + 1)

                'set the function result

                Select Case intResult

                    Case Z_OK : Return intBufferSize 'size of compressed buffer

                    Case Z_MEM_ERROR : Return -4 'not enough memory

                    Case Z_BUF_ERROR : Return -5 'output buffer (m_arbytCompressionBuffer) too small

                    Case Else

                        Return -1 'unknown error

                End Select

            End Function 'intCompressByteArray

            'decompress a byte array into an uncompressed buffer, return value:

            ' the size of the compressed buffer if the operation was successful

            ' return -1 if the operation was unsuccessful but no specific error is provided

            ' return -4 if there was not enough memory to complete the operation

            ' return -5 if there was not enough room in the output buffer (intBufferSize not large enough)

            Public Function intDeCompressByteArray(ByRef arbytData() As Byte) As Integer

                'parameters: arbytData is a one dimensional array of bytes that have been compressed

                ' note:  you need to set the value of m_lngOriginalSize before calling this

                '        function, it requires the original size of the data before compression

                Dim intResult As Integer 'result of the call to zlibwapi.dll

                Dim intBufferSize As Integer 'size of the uncompressed byte array being passed in

                'set the size of the buffer for the data to be uncompressed into; the buffer size

                'must be at least the uncompressed data, plus 12 bytes. after

                'the function is successful, intBufferSize will be the actual size of the

                'uncompressed buffer

                intBufferSize = CInt(m_lngOriginalSize)

                'redimension the decompression buffer to the correct size

                'for this operation

                ReDim m_arbytDeCompressionBuffer(intBufferSize)

                'call the zlibwapi.dll function "compress" to actually compress the bytes

                'intResult = uncompress(m_arbytDeCompressionBuffer, intBufferSize, arbytData, UBound(arbytData) + 1)

                intResult = UncompressByteArray(m_arbytDeCompressionBuffer, intBufferSize, arbytData, UBound(arbytData) + 1)

                'set the function result

                Select Case intResult

                    Case Z_OK : Return intBufferSize 'size unof compressed buffer

                    Case Z_MEM_ERROR : Return -4 'not enough memory

                    Case Z_BUF_ERROR : Return -5 'output buffer (m_arbytCompressionBuffer) too small

                    Case Else

                        Return -1 'unknown error

                End Select

            End Function 'intDeCompressByteArray

        End Class

    End Namespace

    [/code]

  • mercredi 14 mars 2012 01:40
     
      A du code

    Apart from having Option Strict Off, the only problem I see at first glance are the lines

                         Catch ex As Exception
                            ex.Message.ToString()
    

    because exceptions are just swallowed. Are you sure no exception occurs?

    However I haven't had a closer look yet.


    Armin

  • vendredi 30 mars 2012 18:17
     
     Traitée
    Armin is correct, and if my exception handling had done something with the exception, I could have found the true cause of the error much sooner.  2 bad coding mistakes - not handling the exception and then continuting on when there was an exception. The application continued on even though the decompression never happened.  Thankfully through the help of Microsoft support we got an answer that fixed the problem.  IT was this:  On the IIS go to “Application Pools” for this application and change “Enable 32 bit applications” to TRUE.  Now they can view the documents!

    • Marqué comme réponse mpls_bren vendredi 30 mars 2012 18:17
    • Modifié mpls_bren lundi 2 avril 2012 12:49
    •