Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.IO.Compression.ZipFile .NET 4.5 output zip in not suitable for Linux/Mac/Java

Tags:

.net

zip

While using .NET System.IO.Compression.ZipFile.CreateFromDirectory class the outcome zip is badly extracted on system with forward-slash directory separator.

Reason: The zip contains backslash inside the names

like image 770
AdiA Avatar asked Dec 04 '14 08:12

AdiA


3 Answers

To overcome this problem a workaround exists:

    class MyEncoder : UTF8Encoding
    {
        public MyEncoder()
        {

        }
        public override byte[] GetBytes(string s)
        {
            s = s.Replace("\\", "/");
            return base.GetBytes(s);
       }
    }
    System.IO.Compression.ZipFile.CreateFromDirectory("C:/ABC", "C:/tmp/ABC.zip", CompressionLevel.Fastest, false, new MyEncoder());
like image 119
AdiA Avatar answered Oct 17 '22 21:10

AdiA


Microsoft has addressed this in .NET 4.6.1:

Starting with apps that target the .NET Framework 4.6.1, the path separator used in the ZipArchiveEntry.FullName property has changed from the backslash ("\") used in previous versions of the .NET Framework to a forward slash ("/"). System.IO.Compression.ZipArchiveEntry objects are created by calling one of the overloads of the ZipFile.CreateFromDirectory method.

Note:

In addition, apps that target previous versions of the .NET Framework but are running on the .NET Framework 4.6.1 and later versions can opt in to this behavior by adding a configuration setting to the section of the application configuration file.

like image 30
Nathan Arthur Avatar answered Oct 17 '22 23:10

Nathan Arthur


The correct work around for this issue is as follows

class MyEncoder : UTF8Encoding
{
    public MyEncoder() : base(true)
    {

    }
    public override byte[] GetBytes(string s)
    {
        s = s.Replace("\\", "/");
        return base.GetBytes(s);
   }
}

NOTE: This is slightly different from a previous answer.

The key difference is in the : base(true)

This is important or the .NET ZipArchive class will NOT recognize the encoder as a UTF-8 encoder and will NOT mark the correct general purpose bit, and thus extracting the resulting zip file with any other zip program will assume the zip entry name is in a non-unicode encoding which might result in a mangled filename.

The reason is due to a internal call in .NET to check if the custom encoder is .equals(Encoding.UTF8) which isn't true unless true is passed for the encoderShouldEmitUTF8Identifier like Encoding.UTF8

like image 43
MerickOWA Avatar answered Oct 17 '22 23:10

MerickOWA