Forum Discussion
Failure to extract file from ZIP
- 6 years agoHave you tried the implementation I posted here: https://community.powerbi.com/t5/Power-Query/How-to-connect-Azure-DevOps-REST-API-in-to-power-bi/m-p/895318/highlight/true#M30599
- 6 years ago
Here is a version that should work with all of your ZIP files. It ignores the local file entries and grabs the data from the central directory instead. Please test it out.
// expects full path to the ZIP file, only extracts the first data file after getting its size from the central directory // https://en.wikipedia.org/wiki/Zip_(file_format)#Structure (ZIPFile) => let //read the entire ZIP file into memory - we'll use it often so this is worth it Source = Binary.Buffer(File.Contents(ZIPFile)), // get the full size of the ZIP file Size = Binary.Length(Source), //Find the start of the central directory at the sixth to last byte Directory = BinaryFormat.Record([ MiscHeader=BinaryFormat.Binary(Size-6), Start=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian) ]) , Start = Directory(Source)[Start], //find the first entry in the directory and get the compressed file size FirstDirectoryEntry = BinaryFormat.Record([ MiscHeader=BinaryFormat.Binary(Start+20), FileSize=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger32, ByteOrder.LittleEndian), UnCompressedFileSize=BinaryFormat.Binary(4), FileNameLen=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian), ExtrasLen=BinaryFormat.ByteOrder(BinaryFormat.UnsignedInteger16, ByteOrder.LittleEndian) ]) , //figure ou where the raw data starts Offset = 30+FirstDirectoryEntry(Source)[FileNameLen]+FirstDirectoryEntry(Source)[ExtrasLen], Compressed = FirstDirectoryEntry(Source)[FileSize]+1, //get the raw data of the compressed file Raw = BinaryFormat.Record([ Header=BinaryFormat.Binary(Offset), Data=BinaryFormat.Binary(Compressed) ]) // unzip it in Binary.Decompress(Raw(Source)[Data], Compression.Deflate)Name it unzip and and then call it like this
let Source = unzip("C:\downloads\doesnotwork.zip"), #"Imported CSV" = Csv.Document(Source,[Delimiter=",", Encoding=1252, QuoteStyle=QuoteStyle.None]) in #"Imported CSV"
lbendlin firstly thanks for your efforts & excellent analysis, I really appreacite it.
I have tried your code, but at the moment it is only returning the first column from the zip file:
Remove and reapply the csv import step.
- Anonymous6 years agoNot applicable
Sorry, but I don't understand??
- lbendlin6 years ago
Super User
the .Buffer functions load the data once into memory and avoid reloading it over and over again (as is done in the original code)
- Anonymous6 years agoNot applicable
that part I understand.
What I don't understand is what you meant by "Remove and reapply the csv import step" or how to get all the columns from the zip