locked
Zipping files in Gridview RRS feed

  • Question

  • User-1767698477 posted

    I'm using the Ionic.zip dll file to zip my file names which are loaded into a Gridview and save to a location. Is it possible to do this without prompting the user ? When clicking the button, it asks what do you want to do with the file? Save, open, cancel? I tried looking here, but I don't see what to do.  Is it necessary to modify the source code to make it not prompt the user to download the zip file?

    https://documentation.help/DotNetZip/documentation.pdf

     Protected Sub DownloadFiles(ByVal Array As ArrayList)
    Using zip As ZipFile = New ZipFile()
    zip.AlternateEncodingUsage = ZipOption.AsNecessary
    zip.Password = "123"
    zip.AddDirectoryByName("Files")
    ' Create dir otherwise it will store here C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\1003_10-10.pdf
    Dim localpath As String = "c:/mortgageloanapply/users/" + Session("path") + "/" + Session("docpath") + "/"
    'Dim localpath As String = "h:\root\home\pacwest-001\www\MortgageLoanApply\users\" + Session("path") + "/" + Session("docpath") + "/"
    For Each file In Array
    zip.AddFile(localpath + file, "Files")
    Next
    Response.Clear()
    Response.BufferOutput = False
    Response.ContentType = "application/zip"
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + ".zip")
    zip.Save(Response.OutputStream)
    zip.Save(localpath & Session("docpath") & ".zip")
    Response.[End]()
    Emailprocessor(localpath)
    End Using
    End Sub

    I'm editing this post. I'm trying to make it save the file to the local path I want. I get the message :

    Could not find file 'c:\mortgageloanapply\users\120491\Borrower2222\Borrower2222.zip'.

    This is just after I click the button in my browser asking me if I want to save the .zip file that it just created.  Why won't it go into my path which I define and save it? Why does it go and look for the file first ? If I don't put into the path, I get this error message: Access to the path 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\DotNetZip-iwoftakj.tmp' is denied.

    Tuesday, April 21, 2020 5:48 PM

Answers

  • User-1330468790 posted

    Hi sking,

     

    Is it possible to do this without prompting the user ? When clicking the button, it asks what do you want to do with the file? Save, open, cancel? I tried looking here, but I don't see what to do.  Do I have to modify the source code to make it not prompt the user?

    I do not think it is a good design to provide the users with the options you said.

    If you give a save button, users click the button and the purpose is obvious => He/She would like to save the file. Therefore, as you described, he/she will get a zip which contains all of the file inside a directory.

    If you give a open button alongside with save, what will happen when users click the open? The files will be opened one by one or at the same time? 

     

    Suggestion:

    What I suggest is provide a open button inline with each row of the file and outside the group list of the files, you could provide a save button for saving the files as a zip file.

    The code and demonstration will be posted at the end.

     

    This is just after I click the button in my browser asking me if I want to save the .zip file that it just created.  Why won't it go into my path which I define and save it? Why does it go and look for the file first ? If I don't put into the path, I get this error message: Access to the path 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\DotNetZip-iwoftakj.tmp' is denied.

    The reason is located at the below code which is commented with red background. You already saved the file to the output stream and you looked for a file <localpath & Session("docpath") & ".zip> again before you ended the response. Thus, you get an error like [Could not find file <localpath & Session("docpath") & ".zip>] since you don't save any file at this location of the server.

     Protected Sub DownloadFiles(ByVal Array As ArrayList)
    Using zip As ZipFile = New ZipFile()
    zip.AlternateEncodingUsage = ZipOption.AsNecessary
    zip.Password = "123"
    zip.AddDirectoryByName("Files")
    ' Create dir otherwise it will store here C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\1003_10-10.pdf
    Dim localpath As String = "c:/mortgageloanapply/users/" + Session("path") + "/" + Session("docpath") + "/"
    'Dim localpath As String = "h:\root\home\pacwest-001\www\MortgageLoanApply\users\" + Session("path") + "/" + Session("docpath") + "/"
    For Each file In Array
    zip.AddFile(localpath + file, "Files")
    Next
    Response.Clear()
    Response.BufferOutput = False
    Response.ContentType = "application/zip"
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + ".zip")
    zip.Save(Response.OutputStream)
    zip.Save(localpath & Session("docpath") & ".zip")
    Response.[End]()
    Emailprocessor(localpath)
    End Using
    End Sub

     

    Demo for list files and open + save function:

    I take .pdf file type as an example. If you have special type requirement, you should change the response accordingly.

    .aspx:

     <form id="form1" runat="server">
             <div>
                <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowCommand="GridView1_RowCommand">
                    <Columns>
                        <asp:TemplateField HeaderText="Files">
                            <ItemTemplate>
                                <asp:Label ID="Label1" runat="server" Text='<%# Eval("filePath")%>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:Button runat="server" ID="OpenButton"
                                    Text="Open File"
                                    CommandName="OpenFile"
                                    CommandArgument="<%# (CType(Container, GridViewRow)).RowIndex %>" />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
                <asp:Button ID="downloadBtn" runat="server" OnClick="downloadBtn_Click" Text="Download Files" />
            </div>
        </form>

    code behind:

    Private Shared _gridviewDT As DataTable
    
        Public Shared Property GridviewDT As DataTable
            Get
    
                If _gridviewDT Is Nothing Then
                    _gridviewDT = New DataTable()
                    _gridviewDT.Columns.Add("filePath", GetType(String))
                    _gridviewDT.Rows.Add("123.pdf")
                    _gridviewDT.Rows.Add("321.pdf")
                End If
    
                Return _gridviewDT
            End Get
            Set(ByVal value As DataTable)
                _gridviewDT = value
            End Set
        End Property
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack Then
                BindGridView()
            End If
        End Sub
    
        Private Sub BindGridView()
            GridView1.DataSource = GridviewDT
            GridView1.DataBind()
        End Sub
    
        Protected Sub downloadBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
            Dim downloadFileName = String.Format("YourDownload-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss"))
            Response.ContentType = "application/zip"
            Response.AddHeader("Content-Disposition", "filename=" & downloadFileName)
    
            Using zip = New ZipFile()
                zip.Password = "123"
                Dim filePath As String = "C:\Users\xxxxxxx\Desktop\TestResource\PDF\"
                Dim readMeMessage = String.Format("Your ZIP file {0} contains the following files:{1}{1}", downloadFileName, Environment.NewLine)
    
                For Each row As GridViewRow In GridView1.Rows
                    Dim fileName = (CType(row.FindControl("Label1"), Label)).Text
                    readMeMessage += String.Concat(vbTab & "* ", fileName, Environment.NewLine)
                    zip.AddFile(filePath & fileName, "Your Files")
                Next
    
                zip.AddEntry("README.txt", readMeMessage, Encoding.ASCII)
                zip.Save(Response.OutputStream)
            End Using
        End Sub
    
        Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
            If e.CommandName = "OpenFile" Then
                Dim index As Integer = Convert.ToInt32(e.CommandArgument)
                Dim row As GridViewRow = GridView1.Rows(index)
                Dim filePath As String = "C:\Users\xxxxxxx\Desktop\TestResource\PDF\"
                Dim fileName = (CType(row.FindControl("Label1"), Label)).Text
                Response.Clear()
                Response.AddHeader("Content-Disposition", "inline;filename=myfile.pdf")
                Response.ContentType = "application/pdf"
                Response.WriteFile(filePath & fileName)
                Response.[End]()
            End If
        End Sub

    Demo:

     

     

    Hope this can help you.

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, April 22, 2020 3:24 AM

All replies

  • User-1330468790 posted

    Hi sking,

     

    Is it possible to do this without prompting the user ? When clicking the button, it asks what do you want to do with the file? Save, open, cancel? I tried looking here, but I don't see what to do.  Do I have to modify the source code to make it not prompt the user?

    I do not think it is a good design to provide the users with the options you said.

    If you give a save button, users click the button and the purpose is obvious => He/She would like to save the file. Therefore, as you described, he/she will get a zip which contains all of the file inside a directory.

    If you give a open button alongside with save, what will happen when users click the open? The files will be opened one by one or at the same time? 

     

    Suggestion:

    What I suggest is provide a open button inline with each row of the file and outside the group list of the files, you could provide a save button for saving the files as a zip file.

    The code and demonstration will be posted at the end.

     

    This is just after I click the button in my browser asking me if I want to save the .zip file that it just created.  Why won't it go into my path which I define and save it? Why does it go and look for the file first ? If I don't put into the path, I get this error message: Access to the path 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\DotNetZip-iwoftakj.tmp' is denied.

    The reason is located at the below code which is commented with red background. You already saved the file to the output stream and you looked for a file <localpath & Session("docpath") & ".zip> again before you ended the response. Thus, you get an error like [Could not find file <localpath & Session("docpath") & ".zip>] since you don't save any file at this location of the server.

     Protected Sub DownloadFiles(ByVal Array As ArrayList)
    Using zip As ZipFile = New ZipFile()
    zip.AlternateEncodingUsage = ZipOption.AsNecessary
    zip.Password = "123"
    zip.AddDirectoryByName("Files")
    ' Create dir otherwise it will store here C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\1003_10-10.pdf
    Dim localpath As String = "c:/mortgageloanapply/users/" + Session("path") + "/" + Session("docpath") + "/"
    'Dim localpath As String = "h:\root\home\pacwest-001\www\MortgageLoanApply\users\" + Session("path") + "/" + Session("docpath") + "/"
    For Each file In Array
    zip.AddFile(localpath + file, "Files")
    Next
    Response.Clear()
    Response.BufferOutput = False
    Response.ContentType = "application/zip"
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + ".zip")
    zip.Save(Response.OutputStream)
    zip.Save(localpath & Session("docpath") & ".zip")
    Response.[End]()
    Emailprocessor(localpath)
    End Using
    End Sub

     

    Demo for list files and open + save function:

    I take .pdf file type as an example. If you have special type requirement, you should change the response accordingly.

    .aspx:

     <form id="form1" runat="server">
             <div>
                <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowCommand="GridView1_RowCommand">
                    <Columns>
                        <asp:TemplateField HeaderText="Files">
                            <ItemTemplate>
                                <asp:Label ID="Label1" runat="server" Text='<%# Eval("filePath")%>'></asp:Label>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:Button runat="server" ID="OpenButton"
                                    Text="Open File"
                                    CommandName="OpenFile"
                                    CommandArgument="<%# (CType(Container, GridViewRow)).RowIndex %>" />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
                <asp:Button ID="downloadBtn" runat="server" OnClick="downloadBtn_Click" Text="Download Files" />
            </div>
        </form>

    code behind:

    Private Shared _gridviewDT As DataTable
    
        Public Shared Property GridviewDT As DataTable
            Get
    
                If _gridviewDT Is Nothing Then
                    _gridviewDT = New DataTable()
                    _gridviewDT.Columns.Add("filePath", GetType(String))
                    _gridviewDT.Rows.Add("123.pdf")
                    _gridviewDT.Rows.Add("321.pdf")
                End If
    
                Return _gridviewDT
            End Get
            Set(ByVal value As DataTable)
                _gridviewDT = value
            End Set
        End Property
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack Then
                BindGridView()
            End If
        End Sub
    
        Private Sub BindGridView()
            GridView1.DataSource = GridviewDT
            GridView1.DataBind()
        End Sub
    
        Protected Sub downloadBtn_Click(ByVal sender As Object, ByVal e As EventArgs)
            Dim downloadFileName = String.Format("YourDownload-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss"))
            Response.ContentType = "application/zip"
            Response.AddHeader("Content-Disposition", "filename=" & downloadFileName)
    
            Using zip = New ZipFile()
                zip.Password = "123"
                Dim filePath As String = "C:\Users\xxxxxxx\Desktop\TestResource\PDF\"
                Dim readMeMessage = String.Format("Your ZIP file {0} contains the following files:{1}{1}", downloadFileName, Environment.NewLine)
    
                For Each row As GridViewRow In GridView1.Rows
                    Dim fileName = (CType(row.FindControl("Label1"), Label)).Text
                    readMeMessage += String.Concat(vbTab & "* ", fileName, Environment.NewLine)
                    zip.AddFile(filePath & fileName, "Your Files")
                Next
    
                zip.AddEntry("README.txt", readMeMessage, Encoding.ASCII)
                zip.Save(Response.OutputStream)
            End Using
        End Sub
    
        Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
            If e.CommandName = "OpenFile" Then
                Dim index As Integer = Convert.ToInt32(e.CommandArgument)
                Dim row As GridViewRow = GridView1.Rows(index)
                Dim filePath As String = "C:\Users\xxxxxxx\Desktop\TestResource\PDF\"
                Dim fileName = (CType(row.FindControl("Label1"), Label)).Text
                Response.Clear()
                Response.AddHeader("Content-Disposition", "inline;filename=myfile.pdf")
                Response.ContentType = "application/pdf"
                Response.WriteFile(filePath & fileName)
                Response.[End]()
            End If
        End Sub

    Demo:

     

     

    Hope this can help you.

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, April 22, 2020 3:24 AM
  • User-1767698477 posted

    Hi Sean,

    Thanks for looking at that.  I have worked on this for 3+ hours today.  I have it saving to my local folder where once saved, it is attached to an email and beamed off to the party who will be receiving it. Let's be clear, all I want is a zipping utility that zips up the files in my grid and stores them into a folder. I don't want any popup asking if I want to open, cancel or save the zip.  So I'll ask again, how do I turn that off with this program ?  I require that it be turned off. My website requires high security. It will be storing documents that contain sensitive information.  (like SSN, bank documents, etc) I will allow the person logged in to view the documents though. I think your idea is good putting in on each line of the gridview.  I have not had a chance to experiment with that. This code below is working for me on my local machine and my live one. I commented out the zip.Save(Response.OutputStream) line but it still prompts the user about the file.

    Protected Sub ZipandEmail_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ZipandEmail.Click
    Dim currentRowDocFileName As String
    Dim al As ArrayList = New ArrayList()
    'Enumerate the GridViewRows
    For index As Integer = 0 To GridView1.Rows.Count - 1
    'Programmatically access the CheckBox from the TemplateField
    Dim cb As CheckBox = CType(GridView1.Rows(index).FindControl("RowLevelCheckBox"), CheckBox)

    'If it's checked, then grab something else on the row
    If cb.Checked Then
    currentRowDocFileName = GridView1.DataKeys(index).Value
    Summary.Text &= String.Concat(currentRowDocFilename + ",")
    al.Add(currentRowDocFileName)
    End If
    Next
    DownloadFiles(al)
    End Sub

    Protected Sub DownloadFiles(ByVal Array As ArrayList)

    Dim localpath As String = "c:/mortgageloanapply/users/" + Session("path") + "/" + Session("docpath") + "/"
    Using zip As ZipFile = New ZipFile(localpath)
    zip.AlternateEncodingUsage = ZipOption.AsNecessary
    zip.Password = "123"
    zip.AddDirectoryByName("Files")

    For Each file In Array
    zip.AddFile(localpath + file, "Files")
    Next
    Response.Clear()
    Response.BufferOutput = False
    Response.ContentType = "application/zip"
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + ".zip")
    'zip.Save(Response.OutputStream)
    zip.Save(localpath & Session("docpath") & ".zip") 'Session("docpath") is the folder as well as the file name
    Emailprocessor(localpath)
    End Using
    End Sub

    Wednesday, April 22, 2020 5:39 AM
  • User-1330468790 posted

    Hi sking,

     

    Let's be clear, all I want is a zipping utility that zips up the files in my grid and stores them into a folder. I don't want any popup asking if I want to open, cancel or save the zip.  So I'll ask again, how do I turn that off with this program ?  I require that it be turned off.

    As far as I know, the popup is a feature of the browsers. The server side has nothing to do with that. 

    I need to confirm that I understand your purpose correctly. Could you please answer the following questions?

    • You click the button, and the files will be zipped and stored in a) Client side b) Server side? Which one? Then, the zip file will be sent to others through email.
    • You want to remove the prompt/popup when you click the button "ZipAndEmail". The prompt/popup appears in the browsers, right?

      

    The reason why I asked above questions is that if you care about security, you would not allow the users to download the zip file but the code you provide does transport the file to users'side. If you only need to zip the file and email them to your customers/other parties, I think we need to modify the code.

     

    Best regards,

    Sean

    Wednesday, April 22, 2020 8:14 AM
  • User-1767698477 posted

    Hi Sean,

    Files are saved on server side. I have this working ok.

    I'm going to add a link to the far right side of the each item on the gridview. It will open the document in some kind of viewer. Only allows for viewing the documents. Can't print.

    Do you know of a program that works well in asp.net for viewing pdf files?

    Thursday, April 23, 2020 4:00 AM
  • User-1330468790 posted

    Hi sking,

     

    I am afraid that users can not be limited to download/print the files through viewer/browser. Even you could disable the toolbar on the browser, the file is already downloaded to somewhere in user's computer.

    Instead, I suggest you use iTextSharp (a free pdf processing library) to encrypt the pdf file before transfer it to the client side.

    It is possible to add password and limit user to execute printing, copying, modifying etc. on the PDF files.

    You could click the example here to learn how to use it.

     

    Best regards,

    Sean

     

    Thursday, April 23, 2020 6:29 AM
  • User-1767698477 posted

    Hi Sean,

    I have changed my original design plan. I have removed the checkbox on the left side of gridview to allow selection of the files for zipping to just the assistant. The assistant is the person who does the processing of the information and needs the documents, so when they login, they will be presented with the same page with the checkboxes in the gridview. I have no problem allowing this person to download the files directly. The main user will be able to view the documents and that is my next step along with getting the role manager working and I am working on this now. I was able to get the zipped files created for the selected items and they are getting named as fileZ1.ip, fileZ2.zip each time and put into a folder specific to each user. I could not get it to both saving to the folder and outputting to the browser in the same using statment. After several hours I gave up and used a 2nd using statement and it is working.

    Using zip As ZipFile = New ZipFile()
    zip.AlternateEncodingUsage = ZipOption.AsNecessary
    zip.Password = code
    zip.Encryption = EncryptionAlgorithm.PkzipWeak

    For i = 1 To 100
    If Not System.IO.File.Exists(localpath & Session("docpath") & "Z" + i.ToString & ".zip") Then
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + "Z" + i.ToString + ".zip")
    zipfile = Session("docpath") & "Z" + i.ToString & ".zip"
    Exit For
    End If
    Next

    For Each file In Array
    zip.AddFile(localpath & file, "")
    Next
    zip.Password = code
    zip.Save(Response.OutputStream)   <--save to browser
    End Using

    Using zip As ZipFile = New ZipFile()
    zip.Password = code
    zip.Encryption = EncryptionAlgorithm.PkzipWeak

    For i = 1 To 100
    If Not System.IO.File.Exists(localpath & Session("docpath") & "Z" + i.ToString & ".zip") Then
    Response.AddHeader("content-disposition", "attachment; filename=" & Session("docpath") + "Z" + i.ToString + ".zip")
    zipfile = Session("docpath") & "Z" + i.ToString & ".zip"
    Exit For
    End If
    Next
    For Each file In Array
    zip.AddFile(localpath & file, "") <-- save to local folder
    Next

    zip.Password = code
    zip.Save(localpath & zipfile) 'Session("docpath") is the folder as well as the file name

    SentFilestoProcessor(DocIds)
    End Using

    Thursday, April 30, 2020 7:12 PM