PHP解压缩字符串

I'm loading in a Google Drive spreadsheet via the API into PHP. The request returns the XLSX spreadsheet and I need to unzip it. To save me writing the response to a temporary and then calling, say, zip_open(), is there a way I can just pass such method a string?

I think your best option is to create a temporary file and then to unzip it.

// Create a temporary file which creates file with unique file name
$tmp = tempnam(sys_get_temp_dir(), md5(uniqid(microtime(true))));

// Write the zipped content inside
file_put_contents($tmp, $zippedContent);

// Uncompress and read the ZIP archive
$zip = new ZipArchive;
if (true === $zip->open($tmp)) {
    // Do whatever you want with the archive... 
    // such as $zip->extractTo($dir); $zip->close();
}

// Delete the temporary file
unlink($tmp);

I'd write temporary file myself, but you may want to see the first comment here: http://de3.php.net/manual/en/ref.zip.php


wdtemp at seznam dot cz Hi, if you have the RAW CONTENT OF THE ZIP FILE IN A STRING ONLY and you can't create files on your server (because of the SAFE MODE) to be able to create a file which you can then pass to zip_open(), you'll be having hard times getting the uncompressed content of your ZIP data. This may help: I've written simple ZIP decompression function for decompressing the first file from the archive stored in a string (no matter what file it is). It's just about parsing a local file header of the first file, getting raw compressed data of that file and decompression of that data (usually, data in ZIP files are compressed by 'DEFLATE' method, so we'll just decompress it by gzinflate() function then).

<?php
function decompress_first_file_from_zip($ZIPContentStr){
//Input: ZIP archive - content of entire ZIP archive as a string
//Output: decompressed content of the first file packed in the ZIP archive
    //let's parse the ZIP archive
    //(see 'http://en.wikipedia.org/wiki/ZIP_%28file_format%29' for details)
    //parse 'local file header' for the first file entry in the ZIP archive
    if(strlen($ZIPContentStr)<102){
        //any ZIP file smaller than 102 bytes is invalid
        printf("error: input data too short<br />
");
        return '';
    }
    $CompressedSize=binstrtonum(substr($ZIPContentStr,18,4));
    $UncompressedSize=binstrtonum(substr($ZIPContentStr,22,4));
    $FileNameLen=binstrtonum(substr($ZIPContentStr,26,2));
    $ExtraFieldLen=binstrtonum(substr($ZIPContentStr,28,2));
    $Offs=30+$FileNameLen+$ExtraFieldLen;
    $ZIPData=substr($ZIPContentStr,$Offs,$CompressedSize);
    $Data=gzinflate($ZIPData);
    if(strlen($Data)!=$UncompressedSize){
        printf("error: uncompressed data have wrong size<br />
");
        return '';
    }
    else return $Data;
}

function binstrtonum($Str){
//Returns a number represented in a raw binary data passed as string.
//This is useful for example when reading integers from a file,
// when we have the content of the file in a string only.
//Examples:
// chr(0xFF) will result as 255
// chr(0xFF).chr(0xFF).chr(0x00).chr(0x00) will result as 65535
// chr(0xFF).chr(0xFF).chr(0xFF).chr(0x00) will result as 16777215
    $Num=0;
    for($TC1=strlen($Str)-1;$TC1>=0;$TC1--){ //go from most significant byte
        $Num<<=8; //shift to left by one byte (8 bits)
        $Num|=ord($Str[$TC1]); //add new byte
    }
    return $Num;
}
?> 

Have a look at the zlib functions (if available on your system). As far as i know there is something like zlib-decode (or so), which can handle raw zip data.