Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract a file from a ZIP string

Tags:

I have a BASE64 string of a zip file that contains one single XML file.

Any ideas on how I could get the contents of the XML file without having to deal with files on the disk?

I would like very much to keep the whole process in the memory as the XML only has 1-5k.

It would be annoying to have to write the zip, extract the XML and then load it up and delete everything.

like image 964
transilvlad Avatar asked Feb 28 '13 16:02

transilvlad


People also ask

How do I extract a single file from a zip file?

To unzip a single file or folder, open the zipped folder, then drag the file or folder from the zipped folder to a new location. To unzip all the contents of the zipped folder, press and hold (or right-click) the folder, select Extract All, and then follow the instructions.

How do I extract a ZIP file in Python?

Python3. # into a specific location. Import the zipfile module Create a zip file object using ZipFile class. Call the extract() method on the zip file object and pass the name of the file to be extracted and the path where the file needed to be extracted and Extracting the specific file present in the zip.


2 Answers

I had a similar problem, I ended up doing it manually.
https://www.pkware.com/documents/casestudies/APPNOTE.TXT

This extracts a single file (just the first one), no error/crc checks, assumes deflate was used.

// zip in a string $data = file_get_contents('test.zip');  // magic $head = unpack("Vsig/vver/vflag/vmeth/vmodt/vmodd/Vcrc/Vcsize/Vsize/vnamelen/vexlen", substr($data,0,30)); $filename = substr($data,30,$head['namelen']); $raw = gzinflate(substr($data,30+$head['namelen']+$head['exlen'],$head['csize']));  // first file uncompressed and ready to use file_put_contents($filename,$raw); 
like image 118
toster-cx Avatar answered Oct 21 '22 08:10

toster-cx


After some hours of research I think it's surprisingly not possible do handle a zip without a temporary file:

  1. The first try with php://memory will not work, beacuse it's a stream that cannot be read by functions like file_get_contents() or ZipArchive::open(). In the comments is a link to the php-bugtracker for the lack of documentation of this problem.
  2. There is a stream support ZipArchive with ::getStream() but as stated in the manual, it only supports reading operation on an opened file. So you cannot build a archive on-the-fly with that.
  3. The zip:// wrapper is also read-only: Create ZIP file with fopen() wrapper
  4. I also did some attempts with the other php wrappers/protocolls like

     file_get_contents("zip://data://text/plain;base64,{$base64_string}#test.txt")  $zip->open("php://filter/read=convert.base64-decode/resource={$base64_string}")  $zip->open("php://filter/read=/resource=php://memory") 

    but for me they don't work at all, even if there are examples like that in the manual. So you have to swallow the pill and create a temporary file.


Original Answer:

This is just the way of temporary storing. I hope you manage the zip handling and parsing of xml on your own.

Use the php php://memory (doc) wrapper. Be aware, that this is only usefull for small files, because its stored in the memory - obviously. Otherwise use php://temp instead.

<?php  // the decoded content of your zip file $text = 'base64 _decoded_ zip content';  // this will empty the memory and appen your zip content $written = file_put_contents('php://memory', $text);  // bytes written to memory var_dump($written);  // new instance of the ZipArchive $zip = new ZipArchive;  // success of the archive reading var_dump(true === $zip->open('php://memory')); 
like image 37
HenningCash Avatar answered Oct 21 '22 07:10

HenningCash