I would like to gzip compress a file on my server using PHP. Does anyone have an example that would input a file and output a compressed file?
9 Answers
This code does the trick
// Name of the file we're compressing
$file = "test.txt";
// Name of the gz file we're creating
$gzfile = "test.gz";
// Open the gz file (w9 is the highest compression)
$fp = gzopen ($gzfile, 'w9');
// Compress the file
gzwrite ($fp, file_get_contents($file));
// Close the gz file and we're done
gzclose($fp);

- 8,101
- 3
- 51
- 65
-
16Unfortunately this will probably read the entire file into memory, possibly hitting PHP's memory limit on large files. :-( – Simon East Mar 31 '14 at 04:37
-
while w9 is the highest compression ? which is lowest compression, just for packing data in .gz ? – Jan 23 '17 at 16:06
-
@SimonEast hit the point. This function will hit your memory limit on big files (and you know what? gzip is used to compress that kind of big files). The good answer is the one above not this one – Max Cuttins Jul 18 '18 at 11:58
The other answers here load the entire file into memory during compression, which will cause 'out of memory' errors on large files. The function below should be more reliable on large files as it reads and writes files in 512kb chunks.
/**
* GZIPs a file on disk (appending .gz to the name)
*
* From http://stackoverflow.com/questions/6073397/how-do-you-create-a-gz-file-using-php
* Based on function by Kioob at:
* http://www.php.net/manual/en/function.gzwrite.php#34955
*
* @param string $source Path to file that should be compressed
* @param integer $level GZIP compression level (default: 9)
* @return string New filename (with .gz appended) if success, or false if operation fails
*/
function gzCompressFile($source, $level = 9){
$dest = $source . '.gz';
$mode = 'wb' . $level;
$error = false;
if ($fp_out = gzopen($dest, $mode)) {
if ($fp_in = fopen($source,'rb')) {
while (!feof($fp_in))
gzwrite($fp_out, fread($fp_in, 1024 * 512));
fclose($fp_in);
} else {
$error = true;
}
gzclose($fp_out);
} else {
$error = true;
}
if ($error)
return false;
else
return $dest;
}
UPDATE: Gerben has posted an improved version of this function that is cleaner and uses exceptions instead of returning false on an error. See https://stackoverflow.com/a/56140427/195835

- 55,742
- 17
- 139
- 133
-
-
3Very good bit of code. I took the above and created the reverse to decompress a file. The code is fairly quick. – user3759531 Oct 24 '14 at 20:26
Also, you could use php's wrappers, the compression ones. With a minimal change in the code you would be able to switch between gzip, bzip2 or zip.
$input = "test.txt";
$output = $input.".gz";
file_put_contents("compress.zlib://$output", file_get_contents($input));
change compress.zlib://
to (see comment to this answer about zip compression), or to compress.zip://
for zip compressioncompress.bzip2://
to bzip2 compression.

- 22,354
- 11
- 51
- 57
-
I think `compress.zip://` is not supported for compression. See note on http://www.php.net/manual/en/wrappers.compression.php – Alex Feb 06 '13 at 08:54
-
@Alex yes, it seems you are right, and the zip:// wrapper does not support writing nor appending to an already existing file – Carlos Campderrós Feb 06 '13 at 11:12
Simple one liner with gzencode():
gzencode(file_get_contents($file_name));

- 8,110
- 5
- 43
- 49
-
1Perfect, thanks for this pointer. This useful answer has led me to a whole series of **Zlib functions**: https://www.php.net/manual/en/ref.zlib.php – Rounin Jul 11 '20 at 11:50
Here's an improved version. I got rid of all the nested if/else statements, resulting in lower cyclomatic complexity, there's better error handling through exceptions instead of keeping track of a boolean error state, some type hinting and I'm bailing out if the file has a gz extension already. It got a little longer in terms of lines of code, but it's much more readable.
/**
* Compress a file using gzip
*
* Rewritten from Simon East's version here:
* https://stackoverflow.com/a/22754032/3499843
*
* @param string $inFilename Input filename
* @param int $level Compression level (default: 9)
*
* @throws Exception if the input or output file can not be opened
*
* @return string Output filename
*/
function gzcompressfile(string $inFilename, int $level = 9): string
{
// Is the file gzipped already?
$extension = pathinfo($inFilename, PATHINFO_EXTENSION);
if ($extension == "gz") {
return $inFilename;
}
// Open input file
$inFile = fopen($inFilename, "rb");
if ($inFile === false) {
throw new \Exception("Unable to open input file: $inFilename");
}
// Open output file
$gzFilename = $inFilename.".gz";
$mode = "wb".$level;
$gzFile = gzopen($gzFilename, $mode);
if ($gzFile === false) {
fclose($inFile);
throw new \Exception("Unable to open output file: $gzFilename");
}
// Stream copy
$length = 512 * 1024; // 512 kB
while (!feof($inFile)) {
gzwrite($gzFile, fread($inFile, $length));
}
// Close files
fclose($inFile);
gzclose($gzFile);
// Return the new filename
return $gzFilename;
}

- 122
- 4
-
Thanks Gerben. Yes, your version is cleaner, and I agree that exceptions are better here. – Simon East Jan 10 '23 at 05:10
-
If you are looking to just unzip a file, this works and doesn't cause issues with memory:
$bytes = file_put_contents($destination, gzopen($gzip_path, r));

- 67
- 6
It's probably obvious to many, but if any of the program execution functions is enabled on your system (exec
, system
, shell_exec
), you can use them to simply gzip
the file.
exec("gzip ".$filename);
N.B.: Be sure to properly sanitize the $filename
variable before using it, especially if it comes from user input (but not only). It may be used to run arbitrary commands, for example by containing something like my-file.txt && anothercommand
(or my-file.txt; anothercommand
).

- 1,461
- 1
- 11
- 19
-
exec is locked down on most hosting platforms and is a security risk in general to even use exec – Wranorn Jan 16 '18 at 09:08
-
1@Wranorn That's why I indicated “if any of the program execution functions is enabled on your system,” should I have written “on your hosting platform” instead? As for the security, if you don't pass user input to this function, I'm not sure what is the risk. The only warnings in the [PHP documentation](http://php.net/manual/en/function.exec.php) are about using `escapeshellarg()` or `escapeshellcmd()` when passing user-supplied data to the function. – sylbru Jan 16 '18 at 12:46
-
Thank you, this is the best answer for linux servers for own custom projects. If this function uses inside if project without user interactions, for example by cron - it secure for 100% – realmag777 Apr 27 '21 at 21:14
Compress folder for anyone needs
function gzCompressFile($source, $level = 9)
{
$tarFile = $source . '.tar';
if (is_dir($source)) {
$tar = new PharData($tarFile);
$files = scandir($source);
foreach ($files as $file) {
if (is_file($source . '/' . $file)) {
$tar->addFile($source . '/' . $file, $file);
}
}
}
$dest = $tarFile . '.gz';
$mode = 'wb' . $level;
$error = false;
if ($fp_out = gzopen($dest, $mode)) {
if ($fp_in = fopen($tarFile, 'rb')) {
while (!feof($fp_in))
gzwrite($fp_out, fread($fp_in, 1024 * 512));
fclose($fp_in);
} else {
$error = true;
}
gzclose($fp_out);
unlink($tarFile);
} else {
$error = true;
}
if ($error)
return false;
else
return $dest;
}

- 1
- 1