ZipArchive, 3mf and compression

Stefan

Member
Joined
Jun 1, 2021
Messages
7
Programming Experience
1-3
Hi there,
I have a very weird problem I just can't wrap my head around and not even sure where to ask this.
Basically I'm writing a converter for CAD models to the .3mf file format.
.3mf files are renamed .zip files that have a fixed folder structure and use .xml for their internal data.

I use the official 3mf examples for testing my code and here is the problem:
If I use the windows UI to select the files and rightclick -> 'send to zip archive' everything works correctly.
If I use c# ZipFile or sharpziplib to zip the files - the .3mf throws an error.
If I use tar.exe to zip the files the Windows 3D-viewer throws an error but other CAD programs can open the file.

Hp has a filechecker to look for errors in 3mf files and it throws:
the file is in the archive and is in the right place but for some reason wont be found by the interpreter.

Is there someone that can point me in the right direction?maybe zip files have different was to store path information that is not visible to me as the user?
 

Stefan

Member
Joined
Jun 1, 2021
Messages
7
Programming Experience
1-3
Sure,

code is just this
C#:
string startPath = tempFolderPath;
string zipPath = Path.Combine(_Path, _Filename);
ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, false);

attached the some files zipped by Windows, and zipped by c# ZipFile.
If you rename them to *.3mf you can open them in 3D-Viewer
 

Attachments

  • invalid.zip
    1 KB · Views: 2
  • valid.zip
    1 KB · Views: 2

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,904
Location
Sydney, Australia
Programming Experience
10+
I can see that the ratio reported by File Explorer is different for a couple of the files so, assuming that they were from the same source, there certainly seems to be a difference in the way they have been compressed. I don't have time to look any deeper right now though.
 

Stefan

Member
Joined
Jun 1, 2021
Messages
7
Programming Experience
1-3
I attached another pair of examples that, to me, look pretty much identical in compression.
I'm really scratching my head here.
 

Attachments

  • invalid.zip
    1 KB · Views: 1
  • valid.zip
    1 KB · Views: 1

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,194
Location
Norway
Programming Experience
10+
Would the order of entries in the package matter?
invalid.zip said:
3D\3dmodel.model
_rels\.rels
[Content_Types].xml
valid.zip said:
[Content_Types].xml
_rels/.rels
3D/3dmodel.model
 

NoUserHere

Well-known member
Joined
Sep 5, 2018
Messages
2,138
Programming Experience
10+
You're both wasting your time with this as it's a problem I have experienced myself, and you're unlikely to resolve the issue. Because i was also unable to resolve when I looked into this previously. The answer is on p1/#3. It has something to do with how the files are compressed, and any change to libraries or compressed files after a file was compressed will likely not be able to decompress. The same applies to files compressed with different compression settings will certainly not be able to decompress with alternative decompressors. These libs are very finicky.
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,194
Location
Norway
Programming Experience
10+
I noticed a probably more important difference, the invalid zip has back slashes in entry names, the valid one forward slashes.
Funny thing is when I use ZipFile.CreateFromDirectory the entries get forward slashes. Then I found this:
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 .NET Framework to a forward slash ("/").
Are you using an old .Net Framework version?
 

NoUserHere

Well-known member
Joined
Sep 5, 2018
Messages
2,138
Programming Experience
10+
I wonder if adding :

C#:
<runtime>
   <AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=false" />
</runtime>
To the project file would make any difference?

I can't try it, as I don't have those libs, nor do I have my own zip files handy, but you might be onto something here. How on earth is one to know that this "might" be a requirement if working with Zip files on different framework versions? Feck sake Microsoft...

If this works, you will have made this board the only board on the net to provide a solution for this problem. When I was searching around for answers to this, I never found a solution nor worked out the underline issue.
 

Stefan

Member
Joined
Jun 1, 2021
Messages
7
Programming Experience
1-3
Thanks for your help so far guys.
You'll have to take babysteps with me here.

where do I add the
C#:
<runtime>
   <AppContextSwitchOverrides value="Switch.System.IO.Compression.ZipFile.UseBackslash=false" />
</runtime>

in the *.csproj file?
I'm using VS for all of this and targeting .net framework 4.8
 
Last edited:

Stefan

Member
Joined
Jun 1, 2021
Messages
7
Programming Experience
1-3
guys, guys GUYS!
this is it!
I used ZipArchive to insert every file on its own with "/" as path-separator and it works.

C#:
ZipArchive zip = System.IO.Compression.ZipFile.Open(zipPath, ZipArchiveMode.Create);
zip.CreateEntryFromFile(tempPath+@"/[Content_Types].xml", @"[Content_Types].xml");
zip.CreateEntryFromFile(tempPath+@"/_rels/.rels", @"_rels/.rels");
zip.CreateEntryFromFile(tempPath+@"/3D/3dmodel.model", @"3D/3dmodel.model");
zip.Dispose();

Jesus Christ this was a stupid waste of time. Thanks everyone. I'll just leave some keywords here in case other people are looking for a solution.

zip 3mf files with C#
3mf compression not working
3mf file model could not be loaded 3D-Builder
Writing 3mf files from scratch zip c#
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,194
Location
Norway
Programming Experience
10+

NoUserHere

Well-known member
Joined
Sep 5, 2018
Messages
2,138
Programming Experience
10+
Mark p1/#11 as the solution. Well done man, I don't know how you stumbled on that. (y)

When was the Compression added into S/IO @JohnH? - I never recall using those, or maybe I did, but certainly don't remember.... my brain turns into a mushroom every summer with the heatwaves we seem to get every year now. I don't cope well in hot weather. 😂 It makes me forgetful and frustrated!

The inbuilt .net compression seems to work better for comp/decompressing than the available compression libs which is what originally gave me the same trouble as above.
 

JohnH

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
1,194
Location
Norway
Programming Experience
10+
, I don't know how you stumbled on that. (y)

When was the Compression added into S/IO @JohnH?
By looking at the entry names in post 9 (after I posted it).
DeflateStream/GZipStream has been there since .Net 2,, but ZipArchive/ZipFile was added as late as .Net 4.5 (2012). (look at the Applies To section for classes at MS Docs)
There's also the System.IO.Packaging namespace that deals with the exact kind of packaging that 3mf uses - these classes are more difficult to work with and has been around since .Net 3.0. I actually used them for "zipping" in a project long time ago.
 

NoUserHere

Well-known member
Joined
Sep 5, 2018
Messages
2,138
Programming Experience
10+
I can finally dig up my 5 year old zips and unzip them. :)

Previously I wasn't able to rename the extension of a zip file and unzip it with FastZip (sharpziplib), as it would throw an error. I have not put in the suggestion on p1/#12 and It's working and unzipping regardless. I think I know why.
C#:
            bool resultExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "result.zip"));
            if (!resultExist)
                System.IO.Compression.ZipFile.CreateFromDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "result.zip", CompressionLevel.Fastest, false);
            else Debug.WriteLine("File exists");

            bool result3mfExist = File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "result.3mf"));
            if (!result3mfExist && resultExist)
                File.Move(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "result.zip"), Path.ChangeExtension(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "result.zip"), ".3mf"));
            else Debug.WriteLine("File exists");
            //ZipFile.ExtractToDirectory("result.3mf", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "extract"));
            FastZip fZip = new FastZip();
            fZip.ExtractZip(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "result.3mf"), Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "extract"), null);
Uncommenting line 10 also works to unzip if I zip with FastZip instead. But I am zipping/unzipping from the same frameworks version. So now I want to troubleshoot if it works without edited the project file as I suggestion above based on your link.

Which of the attached files in p1/#8 were created not using .net or by using tar.exe? I just want to be sure by confirming this for myself.

but ZipArchive/ZipFile was added as late as .Net 4.5 (2012).
Thank you. Hmm, Microsoft listed different version dates on Nuget : System.IO.Compression 4.3.0
 
Top Bottom