Upload Zip File & Unzip Contents

Thread is closed for posting
2 posts, 1 answers
  1. 45AA9EE6-E8B5-40A0-99F5-6391C10FC799
    45AA9EE6-E8B5-40A0-99F5-6391C10FC799 avatar
    571 posts
    Member since:
    Aug 2004

    Posted 16 Apr 2008 Link to this post

    Requirements

    RadControls version

    Q1 2008

    .NET version

    2.0 +

    Visual Studio version

    2005 +

    programming language

    VB.NET

    browser support

    all browsers supported by RadControls


     
  2. PROJECT DESCRIPTION
    This is a very small project that contains a running example of how to enable a user to upload a zip file in any of the File Browser Dialogs, and then unzip the contents of the zip file to the selected directory.

    Some notes on my own logic used here.  Since the user is allowed to upload a zip file we no longer know for sure what is contained in that file - it could be any combination of any kinds of files and / or directories.  I decided that I liked the feature of the user being able to upload directories of files so the code allows for that.  Essentially, this is the pseudocode:

    1) Is the uploaded file a zip file?  If yes, then goto step 2, otherwise, proceed as normal.
    2) Don't save the zip file to disk, begin extraction in-memory
    3) For each entry in the zip file, determine if it's a file or a directory
    4) If it's a file, delete the file if it already exists.  If it's a directory, create the directory.
    5) Check that the file is a non-zip file that complies with the file types specified in the search patterns.  If it is a valid file, save it to disk.
    6) Check that all directories and sub-directories contain image files.  If the directory is empty, delete it.  This is because a directory in the zip file could have contained an invalid file - but the directory would have still be created.
    7) Try to return the path of the last extracted file to the File Browser Dialog - this doesn't work if the File Browser needs to change a directory but it does work in all other cases.

    For those who don't want to download the whole project from the code library and just want to copy/paste the needed code for their own project, here's how it's done.

    Step 1: Download and add a reference to the SharpZipLib.dll for your website / project.

    Step 2: Extend the built-in FileSystemContentProvider.  The only method that needs to be overridden is the StoreFile method, but you'll also need to create a New(...) method.  Add the following class to your App_Code folder.  Note: to make the code smaller, I've removed all comments but hopefully it makes sense:

    Imports ICSharpCode.SharpZipLib.Zip  
    Imports System.IO  
    Imports Telerik.Web.UI  
    Imports Telerik.Web.UI.Widgets  
     
    Public Class UnzipFileSystemContentProvider  
      Inherits FileSystemContentProvider  
     
      Public Sub New(ByVal context As HttpContext, ByVal searchPatterns As String(), ByVal viewPaths As String(), ByVal uploadPaths As String(), ByVal deletePaths As String(), ByVal selectedUrl As StringByVal selectedItemTag As String)  
        MyBase.New(context, searchPatterns, viewPaths, uploadPaths, deletePaths, selectedUrl, selectedItemTag)  
        Me.ProcessPaths(MyBase.ViewPaths)  
        Me.ProcessPaths(MyBase.UploadPaths)  
        Me.ProcessPaths(MyBase.DeletePaths)  
        MyBase.SelectedUrl = FileBrowserContentProvider.RemoveProtocolNameAndServerName(Me.GetAbsolutePath(MyBase.SelectedUrl))  
      End Sub 
     
      Public Overrides Function StoreFile(ByVal file As UploadedFile, ByVal path As StringByVal name As StringByVal ParamArray arguments As String()) As String 
        Dim relFolder As String = path  
        Dim relFull = IO.Path.Combine(relFolder, name)  
        Dim mapFolder As String = MyBase.Context.Server.MapPath(relFolder)  
        Dim mapFull As String = MyBase.Context.Server.MapPath(relFull)  
        If file.GetExtension = ".zip" Then 
          Dim lastValidFile As String = "" 
          Using ZIS As New ZipInputStream(file.InputStream)  
            Dim ZE As ZipEntry = ZIS.GetNextEntry  
            While Not IsNothing(ZE)  
              Dim strDir As String = IO.Path.GetDirectoryName(ZE.Name)  
              Dim strFil As String = IO.Path.GetFileName(ZE.Name)  
              If strDir.Length > 0 Then 
                IO.Directory.CreateDirectory(mapFolder & strDir)  
              End If 
              If strFil <> String.Empty Then 
                If IsValidFileTypeAfterUnZip(ZE.Name) Then 
                  DeleteFileIfAlreadyExists(mapFolder & ZE.Name)  
                  lastValidFile = relFolder & ZE.Name  
                  Using FS As FileStream = IO.File.Create(mapFolder & ZE.Name)  
                    Dim i As Integer = 2048  
                    Dim b As Byte() = New Byte(2048) {}  
                    While True 
                      i = ZIS.Read(b, 0, b.Length)  
                      If i > 0 Then 
                        FS.Write(b, 0, i)  
                      Else 
                        Exit While 
                      End If 
                    End While 
                  End Using  
                End If 
              End If 
              ZE = ZIS.GetNextEntry  
            End While 
          End Using  
          DeleteEmptyDirectoriesAfterZip(mapFolder)  
          Return lastValidFile  
        Else 
          DeleteFileIfAlreadyExists(mapFull)  
          file.SaveAs(mapFull)  
          Return relFull  
        End If 
      End Function 
     
      Private Sub DeleteFileIfAlreadyExists(ByVal mapFull As String)  
        If IO.File.Exists(mapFull) Then 
          IO.File.Delete(mapFull)  
        End If 
      End Sub 
     
      Private Sub DeleteEmptyDirectoriesAfterZip(ByVal mapFolder As String)  
        For Each Dir As String In IO.Directory.GetDirectories(mapFolder)  
          DeleteEmptyDirectoriesAfterZip(Dir)  
          If IO.Directory.GetFiles(Dir).Count = 0 And IO.Directory.GetDirectories(Dir).Count = 0 Then 
            IO.Directory.Delete(Dir)  
          End If 
        Next 
      End Sub 
     
      Private Function IsValidFileTypeAfterUnZip(ByVal fileName As StringAs Boolean 
        Dim strExt As String = Right(fileName, fileName.Length - fileName.LastIndexOf(".")).ToLower  
        If strExt = ".zip" Then 
          Return False 
        Else 
          For Each s As String In MyBase.SearchPatterns  
            s = Right(s, s.Length - s.LastIndexOf(".")).ToLower  
            If s = strExt Then Return True 
          Next 
        End If 
        Return False 
      End Function 
     
    End Class 
     

    Step 3: Add the "*.zip" extension to the SearchPatterns of the Image/Document/Media/Etc Manager; which unfortunately also means you need to manually re-input all of the default file extensions.  This is what it looks like for the ImageManager (Note: I haven't brought back all of the default extensions):

    <telerik:RadEditor runat="server" ID="RadEditor1" Skin="Default">  
      <ImageManager DeletePaths="~/Images/" SearchPatterns="*.gif,*.jpg,*.jpeg,*.jpe,*.tiff,*.tif,*.bmp,*.png,*.zip" UploadPaths="~/Images/" ViewPaths="~/Images/" /> 
    </telerik:RadEditor>      
     

    Step 4: Set the ContentProviderTypeName for the Image/Document/Media/Etc Manager that you want to enable zip files for:

    RadEditor1.ImageManager.ContentProviderTypeName = GetType(UnzipFileSystemContentProvider).AssemblyQualifiedName  
     

    Step 5: Make sure you add all the other necessary stuff required by the Editor in Q1 2008 and going forward, such as the HttpHandlers in the Web.config and the RadSpell dictionary in the App_Data folder.





    Go to this forum thread for the code and more info:

    http://www.telerik.com/community/forums/thread/b311D-bdcktb.aspx
  • Answer
    DF60784D-55A5-4263-9F10-A12FA48C9ADC
    DF60784D-55A5-4263-9F10-A12FA48C9ADC avatar
    14477 posts
    Member since:
    Apr 2022

    Posted 17 Apr 2008 Link to this post

    Hi Shaun,

    Thank you for the implementation. Indeed, this is a very useful feature, which will be highly appreciated by the community.

    Best regards,
    Rumen
    the Telerik team

    Instantly find answers to your questions at the new Telerik Support Center
  • Back to Top

    This Code Library is part of the product documentation and subject to the respective product license agreement.