Click here to Skip to main content
15,884,176 members
Articles / Web Development / ASP.NET

How to zip a folder in ASP.NET

Rate me:
Please Sign up or sign in to vote.
3.69/5 (6 votes)
7 Apr 2009CPOL3 min read 40.3K   34   5
Explains how to zip a folder in ASP.NET.

Introduction

This article explains how to zip a folder from ASP.NET, and how a client can download and save the zipped folder locally.

Background

A few months back, in my ASP.NET application, I needed to create a handful of different reports using Crystal Reports and send those reports to the client in PDF format. If I had only one report to display, I could display it in the browser and the client could save it locally. But, the number of reports was quiet large, and I decided to put all the reports generated in a folder created dynamically, zip thes folder, and send the zipped folder to the client. Here, I will explain how I implemented all these steps. Since your overall requirement may be different, I am not giving the complete source code for this.

I have written all the code in VB.NET, using the Visual Studio 2005 IDE, and you can easily convert it to C#.

Generating Crystal Reports in PDF format and displaying it in the browser

Generating Crystal Reports in PDF Format

This code snippet explains how to generate a Crystal Reports report in PDF format and show it in the client browser. I assume you have already created (designed) a report using Crystal Reports.

This function will create the report in PDF format and sent it to the caller as a memory stream:

VB
Public Function CreatePDFStream() As MemoryStream

    Dim newConnectionInfo As ConnectionInfo = GetConnectionInfo()
    Dim report As New ReportDocument
    Dim reportPath As String = Server.MapPath(".\Reports\Myreport.rpt")
    Dim PDFStream As MemoryStream

    report.Load(reportPath, OpenReportMethod.OpenReportByTempCopy)
    SetDBLogonForReport(newConnectionInfo, report)
    SetCurrentValuesForParameterField(report)

    With report
        .ExportOptions.ExportDestinationType = _
          CrystalDecisions.Shared.ExportDestinationType.DiskFile
        .ExportOptions.ExportFormatType = _
          CrystalDecisions.Shared.ExportFormatType.PortableDocFormat
        .Refresh()
        SetCurrentValuesForParameterField(report)
        PDFStream = CType(.ExportToStream(ExportFormatType.PortableDocFormat), _
                                          MemoryStream)
        .Close()
   End With

    Return PDFStream
End Function

In the above function, GetConnectionInfo will simply read the connection details from the config file and store the details in a CrystalDecisions.Shared.ConnectionInfo. This ConnectionInfo is later used by the report to get connected to the server. It is done in the function SetDBLogonForReport, and the same is reproduced bewlow.

ConnectionInfo needs the following properties to be set, and the code is given below:

VB
With newConnectionInfo
        DatabaseName = conn.Database
        ServerName = conn.Server
        UserID = conn.User
        .Password = conn.Password
End With

SetDBLogOnForReport will set the connection and databsae properties for the report, and here is the code:

VB
Private Sub SetDBLogonForReport(ByVal connectionInfo As ConnectionInfo, _
            ByVal myReportDocument As ReportDocument)
    Dim crtableLogoninfos As New TableLogOnInfos()
    Dim crtableLogoninfo As New TableLogOnInfo()
    Dim crConnectionInfo As New ConnectionInfo()

    Dim crTables As Tables
    Dim crTable As Table

       crTables = myReportDocument.Database.Tables

    For Each crTable In crTables
        crtableLogoninfo = crTable.LogOnInfo
        crtableLogoninfo.ConnectionInfo = connectionInfo
        crTable.ApplyLogOnInfo(crtableLogoninfo)
        crTable.Location = connectionInfo.DatabaseName & ".dbo." & _
                crTable.Location.Substring(crTable.Location.LastIndexOf(".") + 1)
        crTable.LogOnInfo.ConnectionInfo.ServerName = connectionInfo.ServerName()
    Next

End Sub

After setting the connection details, we need to set the parameters (if any) for the report. In my case, I will get the required parameters from the query string. SetCurrentValuesForParameterField will do the job.

VB
Private Sub SetCurrentValuesForParameterField(ByVal myReportDocument As ReportDocument)

    ProcessQueryString() 'simply extract my parameters from query string

    Dim currentFirstParameteValues As ParameterValues = New ParameterValues()
    Dim currentSecondParameterValues As ParameterValues = New ParameterValues()

    Dim FirstParameterValue As New CrystalDecisions.Shared.ParameterDiscreteValue
    Dim SecondParameterValue As New CrystalDecisions.Shared.ParameterDiscreteValue

    FristParameterValue.Value = xxxxx ' Value from the processed query string
    SecondParameterValue.Value = yyyy ' Value from the processed query string

    currentFirstParameterValues.Add(FirstParameterValue)
    currentSecondParameterValues.Add(SecondParameterValue)
        

    ' Getting info about report parameters
    Dim SSTParameterFieldDefinitions As ParameterFieldDefinitions = _
                      myReportDocument.DataDefinition.ParameterFields

    Dim FirstParameterFieldDefinition As ParameterFieldDefinition = _
                                         SSTParameterFieldDefinitions(0)
    Dim SecondParameterFieldDefinition As ParameterFieldDefinition = _
                                          SSTParameterFieldDefinitions(1)

    'providing current values for the report
    FristParameterFieldDefinition.ApplyCurrentValues(currentFirstParameterValues)
    SecondParameterFieldDefinition.ApplyCurrentValues(currentSecondParameterValues)

End Sub

Showing the PDF report in the browser

Showing the PDF report in browser is really simple:

VB
PDFStream= CreatePDFStream
If Not PDFStream is nothing Then
Response.Clear()
      Response.Buffer = True
      Response.ContentType = "application/pdf"
      Response.BinaryWrite(PDFStream.ToArray())
      Response.End()
      PDFStream.Close()
End If

Zipping a folder

Before explaining how to zip a folder, let me explain how to direct the zipped folder to the browser so that the client can download and save it. This code assumes you know the path to the zipped folder.

VB
'fully qualified path of zipped folder
zippedFolderPath = zippath
Me.Response.Clear()
Me.Response.AddHeader("Content-Disposition", _
                      "attachment; filename=" + _
                      zippedFolderPath)
Me.Response.ContentType = "Application/X-zip-compressed"
Me.Response.WriteFile(zippedFolderPath)
Me.Response.Flush()
'Deleting zipped folder
System.IO.File.Delete(zippedFolderPath)

In order to zip a folder, you need to add a few namespaces. All these namespaces are part of the Visual J# library, vjslib.dll. So first, you need to add this library to the application. You can find this library in the .NET framework version path. In my machine, it is available in C:\Windows\Microsoft.Net\FrameWork\V2.0.50727\vjslib.dll.

The namespaces to be imported are:

VB
Imports java.io
Imports java.util
Imports java.util.zip

The following function will create individual PDF reports, put them in a newly created folder, zip the folder, and return the name of zipped file to the caller:

VB
Private Function CreatePDFFiles() As String
    Dim outPutDirectoryName As String
    outPutDirectoryName = _outputPath + "_" + _sessionID
    createOutputDirectory(outPutDirectoryName) ‘ Create a directory
       Dim zipFileName As String = outPutDirectoryName & ".zip"
    Dim PDFStream As MemoryStream

    ' Creating individual reports 
    For Each kvp As KeyValuePair(Of Integer, String) In details
            
        PDFStream = CreatePDFStream() ‘already explained
        Dim pdfBuffer(CType(PDFStream.Length - 1, Integer)) As Byte
        PDFStream.Read(pdfBuffer, 0, pdfBuffer.Length)
        PDFStream.Close()
        Dim PDFFileName As String
        PDFFileName = outPutDirectoryName + "\" + CreateOutPutPDFFileName(code) 
        Dim PDFFile As New FileStream(PDFFileName, _
                           FileMode.Create, FileAccess.Write)
        PDFFile.Write(pdfBuffer, 0, pdfBuffer.Length)
        PDFFile.Close()

    Next

    'Zipping folder
    If System.IO.Directory.Exists(outPutDirectoryName) Then

        Dim fos As java.io.FileOutputStream
        Dim zos As java.util.zip.ZipOutputStream
        Dim di As System.IO.DirectoryInfo

        'create a zip file with same name in the same path
        If System.IO.File.Exists(zipFileName) Then
            System.IO.File.Delete(zipFileName)
        End If

        fos = New java.io.FileOutputStream(zipFileName)
        zos = New java.util.zip.ZipOutputStream(fos)
        di = New System.IO.DirectoryInfo(outPutDirectoryName)

        'procedure to zip a directory
        ZipFolder(fos, zos, di, outPutDirectoryName)
        zos.close()
        fos.close()
        zos.flush()
        fos.flush()

    End If

    DeleteOutputDirectory(outPutDirectoryName)
    Return zipFileName.Substring(zipFileName.LastIndexOf("\") + 1)

End Function

The ZipFolder procedure will do the zipping:

VB
Private Sub ZipFolder(ByVal fileOutputStream As java.io.FileOutputStream _
                            , ByVal zipOutputStream As java.util.zip.ZipOutputStream _
                            , ByVal directoryInfo As System.IO.DirectoryInfo _
                            , ByVal SRootDir As String)

    Dim fileInputStream As java.io.FileInputStream
    Dim zipEntry As java.util.zip.ZipEntry

    Dim PDFReportInfos As System.IO.FileInfo() = directoryInfo.GetFiles
    Dim PDFReportInfo As System.IO.FileInfo

    For Each PDFReportInfo In PDFReportInfos
        zipEntry = New  java.util.zip.ZipEntry(_
           PDFReportInfo.FullName.Substring(SRootDir.LastIndexOf("\")))

        zipEntry.setMethod(zipEntry.DEFLATED)
        zipOutputStream.putNextEntry(zipEntry)

        fileInputStream = New java.io.FileInputStream(PDFReportInfo.FullName)

    Dim reader As New java.io.InputStreamReader(fileInputStream)
        Dim writer As New java.io.OutputStreamWriter(zipOutputStream)
        While reader.ready
            writer.write(reader.read)
        End While
        writer.flush()

        zipOutputStream.closeEntry()
        fileInputStream.close()
    Next

End Sub

Conclusion

This article only gives you an outline of how to do things, since the complete code is out of the scope.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Photon Infotech, US
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralCould not load file or assembly 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified Pin
Bajrang Singh16-Jun-10 20:17
Bajrang Singh16-Jun-10 20:17 
GeneralWindows blocks the contents of my zipped folder Pin
Apeksha8218-Nov-09 6:00
Apeksha8218-Nov-09 6:00 
GeneralArticle Title Pin
stixoffire17-May-09 18:04
stixoffire17-May-09 18:04 
Generalok article Pin
Donsw10-May-09 17:51
Donsw10-May-09 17:51 
GeneralNice... Pin
Suresh Suthar8-Apr-09 19:59
professionalSuresh Suthar8-Apr-09 19:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.