gzip and return as string - php

I want to compress some files with gzip in PHP..
It works as it should when the output file is saved into a file.. When the file is opened it looks like this
But not when the output is returned as a string.. Then the opened file looks like this.. Why is tar file showed inside the gzip file?
public function compress(){
if($this->stream){
return gzencode($this->data, 9);
}
else{
$gz = gzopen('test.tar.gz', 'w9');
gzwrite($gz, $this->data);
gzclose($gz);
}
}
headers sent with string output to the browser
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.$filename.'"');

This looks like a WinRAR file extension parsing issue.
In the first example your file is called .tar.gz and WinRAR knows how to handle both tar files and gz compression, so it is able to decompress the tar headers in memory and retrieve a list of files contained within.
In your second example the file is called .tar-19.gz, so WinRAR happily deals with the gz compression but has no idea what format tar-19 is supposed to be (it doesn't even try and guess from header heuristics)
I bet if you stream the file with a tar.gz extension it will open up just fine.

I am sure that you looked into http://php.net/manual/en/function.gzcompress.php
make sure that you have php version PHP 4 >= 4.0.1, PHP 5
string gzcompress ( string $data [, int $level = -1 [, int $encoding = ZLIB_ENCODING_DEFLATE ]] )
This function compress the given string using the ZLIB data format.
For details on the ZLIB compression algorithm see the document "» ZLIB Compressed Data Format Specification version 3.3" (RFC 1950).
<?php
$compressed = gzcompress('Compress me', 9);
echo $compressed;
?>
Note:
This is not the same as gzip compression, which includes some header
data. See gzencode() for gzip compression.
Parameters
data
The data to compress.
level
The level of compression. Can be given as 0 for no compression up to 9
for maximum compression.
If -1 is used, the default compression of the zlib library is used which is 6.
encoding
One of ZLIB_ENCODING_* constants.
gzencode — Create a gzip compressed string
<?php
$data = implode("", file("bigfile.txt"));
$gzdata = gzencode($data, 9);
$fp = fopen("bigfile.txt.gz", "w");
fwrite($fp, $gzdata);
fclose($fp);
?>

Have you tried passing "Content-type: application/x-gzip" headers when sending the file as a string?
It's possible Apache is re-running it through a gzip filter and that's causing issues.

Related

How to convert base64 encoded attachment to file (PDF, msg, eml)

We have an XML file exported from ServiceNow which we are trying to import into our custom PHP app.
Each attachment <sys_attachment> are split into chunks <sys_attachment_doc> which is ordered by the <position> element.
<sys_attachment>
<chunk_size_bytes>734003</chunk_size_bytes>
<compressed>true</compressed>
<content_type>application/pdf</content_type>
<encryption_context display_value="" />
<file_name>Filename.pdf</file_name>
</sys_attachment>
<sys_attachment_doc>
<data>[BASE64 ENCODED STRING HERE]</data>
<length>[STRING LENGTH]</length>
<position>0</position>
</sys_attachment_doc>
<sys_attachment_doc>
<data>[BASE64 ENCODED STRING HERE]</data>
<length>[STRING LENGTH]</length>
<position>1</position>
</sys_attachment_doc>
We have tried combining the string and base64_decoding it but to no avail.
<?php
header('Content-type: application/pdf');
header('Content-Disposition: attachment; filename="servicenow.pdf"');
//echo base64_decode($chunk0.$chunk1);
echo base64_decode($chunk0).base64_decode($chunk1);
?>
We are unable to find any documentation on how to convert these attachments to files outside of ServiceNow (PHP). Is there an extra step that needs to be done before decoding the string and converting to file (PDF)
Edit: I manage to solve it using #Joey answer. I base64_decode the chunks then afterwards combine it. The combined string is actually gzip compressed. We used gzdecode() to generate the PDF.
$attachment = base64_decode($chunk0).base64_decode($chunk1);
echo gzdecode($attachment);
One thing that may be tripping you up is that <compressed> flag. Since that's reading as true, the data is also gzipped, so attachments start from byte[], which then get gzipped, broken into chunks, and base64 encoded (per chunk!).
I don't know how to do this in php specifically, but this strategy should work:
Base64 decode of each chunk will give you a byte[] per chunk.
Combine those chunks in order of position to give you one big byte stream
gunzip that stream into another big byte stream which should be your file.

How output data with gzip header and not deflate header

I'm testing compression of html files.
I have 2 HTML files:
Not compressed HTML file ( content will change )
Compressed HTML file .gz ( content won't change )
Using PHP I'm trying to output compressed files data and here begins.
test with already compressed html file.
//header gzip
$data = getfile($name); // custom function packed with fopen fread
header(Content-Encoding: gzip); // header works perfect
echo $data; // output OK
//header deflate
$data = getfile($name); // custom function packed with fopen fread
header(Content-Encoding: deflate); // file was gzip compressed so error is normal
echo $data; // fireFox : Content Encoding Error
test with not compressed html file
//header gzip using gzcompress();
$data = gzcompress(getfile($name), 9);
header(Content-Encoding: gzip); // somehow header is bad
echo $data; // fireFox : Content Encoding Error , but IE 9 output OK
but here we got magic
//header deflate using gzcompress();
$data = gzcompress(getfile($name), 9);
header(Content-Encoding: deflate); // header works perfect
echo $data; // Firefox output OK, but IE output ERROR
How fix this crazy thing and send all data as gzip with gzip header not defalte? maybe someone have any idea what is wrong?
Thank you
The HTTP spec. (RFC2616) says:
gzip
An encoding format produced by the file compression program
"gzip" (GNU zip) as described in RFC 1952 [25].
compress
The encoding format produced by the common UNIX file compression
program "compress".
deflate
The "zlib" format defined in RFC 1950 [31] in combination with
the "deflate" compression mechanism described in RFC 1951 [29].
The PHP docs say:
gzcompress
For details on the ZLIB compression algorithm see the document
"ZLIB Compressed Data Format Specification version 3.3"
(RFC 1950).
gzdeflate
For details on the DEFLATE compression algorithm see the document
"DEFLATE Compressed Data Format Specification version 1.3"
(RFC 1951).
gzencode
For more information on the GZIP file format, see the document:
GZIP file format specification version 4.3 (RFC 1952).
From this, one can come to the conclusion that gzencode() must be used with gzip, and gzcompress() (with the DEFLATE encoding) must be used with deflate.
The first combination works for me. I haven't tried the second; don't know why it wouldn't work with IE. A URL might help to trouble-shoot that problem.

PHP: How to check if gz file is corrupt?

Is there any way to detect if a gz file is corrupt in PHP?
I'm currently using http://www.php.net/manual/de/function.gzread.php#110078 to determine the file size and read the whole* file via
$zd = gzopen ( $file, "r" );
$contents = gzread ( $zd, $fzip_size );
gzclose ( $zd );
Unfortunately some gz files are corrupted and the last 4 bytes do not represent the real length of the gz file. As long as the number is negativ I'm able to tell that something is wrong, but sometimes it's positive (and very large) which leads to an out of memory error. How can I check in advance if the file is corrupted?
I'm reading the whole file because I found no working way to read the file line-by-line without knowing the size of the longest line - which led (in some case) to lines that were not complete.
If you can use linux gzip command it will be very simply to find if file is wrong or not. gzip -t will display no message if file is valid.
if (`gzip -t $file 2>&1`) {
echo "An error occured";
}

Compress gzip string

I want to compress a string in PHP and write it to a file without using the gzwrite function as I want to store the actual compressed string in a database first, but I am unsure as whether to use gzcompress, gzencode or gzdeflate as it's not very clear.
Any ideas?
Edit: the already compressed string will be written into a *.gz file from the database so it has to be compatible.
Use gzcompress if you just want to compress the string.
gzencode will also add gzip file headers so it can be uncompressed directly by gzip and similar tools.
gzdeflate uses the deflate algorithm which is very similar to the first one.
I think yo want to use gzencode in ths case since the data is going to be stored as a file.

GZ Compressing an XML sitemap file with PHP

I have a PHP script that generates a dynamic PHP sitemap from my site's database to an xml file using fopen() and fwrite().
How can I compress this file using GZ compression dynamically as I write it?
I tried fwrite()-ing strings that I ran through gzcompress() into the file and renaming it ".xml.gz", but it doesn't seem the file it;s creating is a well-fromed archive.
Not using fopen and fwrite but gzopen() and gzwrite() should do the trick for you.
From the manual:
# Sample #1 gzwrite() example
<?php
$string = 'Some information to compress';
$gz = gzopen('somefile.gz','w9');
gzwrite($gz, $string);
gzclose($gz);
?>
If i understood correctly
this is a quote from the php site that we all should keep in mind.
Take Heed 07-Nov-2010 08:50 Read the description of gzwrite() very
carefully. If the 'length' option is not specified, then the input
data will have slashes stripped on systems where magic quotes are
enabled. This is important information to know when compressing
files.
http://php.net/manual/en/function.gzwrite.php

Categories