In PHP I've to remove the author metadata from a DOCX file. First of all, I've unzip the document and after I've edit the author metadata setting it empty using an XML reader library.
$file = 'document.docx';
$filename = 'path/'.$file;
// Unzip the docx
$unzipped = md5($filename);
if (file_exists($unzipped)) {
rmdir($unzipped);
mkdir($unzipped);
}
$zip = new ZipArchive;
$res = $zip->open($filename);
if ($res === true) {
extractFolder($zip, "word/media", $unzipped);
$zip->extractTo($unzipped);
$zip->close();
} else {
die("The docx file appears to be corrupt (i.e. it can't be opened using Zip).\n");
}
The problem occurs when I tried to re-zip the document. In fact, when the re-zip is done, the docx file seems to be corrupted when I open it in Word.
create_docx($unzipped,'_zips/'.$file );
How can I modify the author metadata (setting the document anonymous) and save the correct docx file?
I don't know php, but I assume the problem is that you have to compress inside the folder $unzipped, NOT the folder itself. So a kind of recursive "$unzipped/*" as source instead of "$unzipped".
Related
I have a ZIP file on my server. I want to create a PHP file, loadZIP.php that will accept a single parameter, and then modify a text file within the ZIP to reflect that parameter.
So, accessing loadZIP.php?param=blue, will open up the zip file, and replace some text in a text file I specify with 'blue', and allow the user to download this edited zip file.
I've looked over all of the PHP ZIP functions, but I can't find a simple solution. It seems like a relatively easy problem, and I believe I'm over thinking it. Before I go and write some overly complex functions, I was wondering how you'd go about this.
Have you taken a look at PHP5's ZipArchive functions?
Basically, you can use ZipArchive::Open() to open the zip, then ZipArchive::getFromName() to read the file into memory. Then, modify it, use ZipArchive::deleteName() to remove the old file, use ZipArchive::AddFromString() to write the new contents back to the zip, and ZipArchive::close():
$zip = new ZipArchive;
$fileToModify = 'myfile.txt';
if ($zip->open('test1.zip') === TRUE) {
//Read contents into memory
$oldContents = $zip->getFromName($fileToModify);
//Modify contents:
$newContents = str_replace('key', $_GET['param'], $oldContents)
//Delete the old...
$zip->deleteName($fileToModify)
//Write the new...
$zip->addFromString($fileToModify, $newContents);
//And write back to the filesystem.
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
Note ZipArchive was introduced in PHP 5.2.0 (but, ZipArchive is also available as a PECL package).
In PHP 8 you can use ZipArchive::replaceFile
As demonstrated by this example from the docs:
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->replaceFile('/path/to/index.txt', 1);
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>
I have written the PHP script to generate the zip file. it's working fine when I use rar software to extract it but not getting extract with rar software. I can't ask to users to install rar software to extract downloaded zip file.
I don't know where i am commiting mistakes.
Here i attached error screen shot which i get when try to open zip file.
// Here is code snippet
$obj->create_zip($files_to_zip, $dir . '/download.zip');
// Code for create_zip function
//create the archive
$zip = new ZipArchive();
if ($zip->open($destination, $overwrite ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
//add the files
foreach ($valid_files as $file) {
$filearr = explode('/', $file);
$zip->addFile($file, end($filearr));
}
$zip->close();
If $valid_files is a glob'd array, use basename() instead of end(), your zip might not actually have added any files causing for it to be an invalid zip (however that would be visible in the size of the zip file).
Also try winrar/winzip/7zip and see what they return, microsoft's internal zip engine might not be up to date enough to open the zips.
I have also encountered this problem, using 7z solved the problem but we need to send the zip to somebody else so 7z is a nono.
I found that, in my case it is that the file path is too long:
When I use this:
$zip->addFile($files_path.'/people.txt');
And it generated a zip folder nested very deep e.g. ["/tmp/something/something1/something2/people.txt"]
So I need to use this instead
$zip->addFile($files_path.'/people.txt', 'people.txt');
Which generate a a zip folder with only 1 layer ["people.txt"], and Windows Zip read perfectly~
Hope this helps somebody that also have this problem!
I'm trying to zip two files in another directory without zipping the folder hierarchy as well.
The event is triggered by a button press, which causes Javascript to send information using AJAX to PHP. PHP calls a Perl script (to take advantage of Perl's XLSX writer module and the fact that PHP kind of sucks, but I digress...), which puts the files a few folders down the hierarchy. The relevant code is shown below.
system("createFiles.pl -ids ${rows} -test ${test} -path ${path}",$retVal);
`zip ${path}/{$test}_both.zip ${path}/${test}.csv ${path}/${test}.xlsx`;
`zip ${path}/{$test}_csv.zip ${path}/${test}.csv`;
The problem is the zip file has ${path} hierarchy that has to be navigated before the files are shown as seen below:
I tried doing this (cd before each zip command):
system("createFiles.pl -ids ${rows} -test ${test} -path ${path}",$retVal);
`cd ${path}; zip {$test}_both.zip ${test}.csv ${test}.xlsx`;
`cd ${path}; zip {$test}_csv.zip ${test}.csv`;
And it worked, but it seems like a hack. Is there a better way?
The ZipArchive answer by Oldskool is good. I've used ZipArchive and it works. However, I recommend PclZip instead as it is more versatile (e.g. allows for zipping with no compression, ideal if you are zipping up images which are already compressed, much faster). PclZip supports the PCLZIP_OPT_REMOVE_ALL_PATH option to remove all file paths. e.g.
$zip = new PclZip("$path/{$test}_both.zip");
$files = array("$path/$test.csv", "$path/$test.xlsx");
// create the Zip archive, without paths or compression (images are already compressed)
$properties = $zip->create($files, PCLZIP_OPT_REMOVE_ALL_PATH);
if (!is_array($properties)) {
die($zip->errorInfo(true));
}
If you use PHP 5 >= 5.2.0 you can use the ZipArchive class. You can then use the full path as source filename and just the filename as target name. Like this:
$zip = new ZipArchive;
if($zip->open("{$test}_both.zip", ZIPARCHIVE::OVERWRITE) === true) {
// Add the files here with full path as source, short name as target
$zip->addFile("${path}/${test}.csv", "${test}.csv");
$zip->addFile("${path}/${test}.xlsx", "${test}.xlsx");
$zip->close();
} else {
die("Zip creation failed.");
}
// Same for the second archive
$zip2 = new ZipArchive;
if($zip2->open("{$test}_csv.zip", ZIPARCHIVE::OVERWRITE) === true) {
// Add the file here with full path as source, short name as target
$zip2->addFile("${path}/${test}.csv", "${test}.csv");
$zip2->close();
} else {
die("Zip creation failed.");
}
I have a ZIP file on my server. I want to create a PHP file, loadZIP.php that will accept a single parameter, and then modify a text file within the ZIP to reflect that parameter.
So, accessing loadZIP.php?param=blue, will open up the zip file, and replace some text in a text file I specify with 'blue', and allow the user to download this edited zip file.
I've looked over all of the PHP ZIP functions, but I can't find a simple solution. It seems like a relatively easy problem, and I believe I'm over thinking it. Before I go and write some overly complex functions, I was wondering how you'd go about this.
Have you taken a look at PHP5's ZipArchive functions?
Basically, you can use ZipArchive::Open() to open the zip, then ZipArchive::getFromName() to read the file into memory. Then, modify it, use ZipArchive::deleteName() to remove the old file, use ZipArchive::AddFromString() to write the new contents back to the zip, and ZipArchive::close():
$zip = new ZipArchive;
$fileToModify = 'myfile.txt';
if ($zip->open('test1.zip') === TRUE) {
//Read contents into memory
$oldContents = $zip->getFromName($fileToModify);
//Modify contents:
$newContents = str_replace('key', $_GET['param'], $oldContents)
//Delete the old...
$zip->deleteName($fileToModify)
//Write the new...
$zip->addFromString($fileToModify, $newContents);
//And write back to the filesystem.
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
Note ZipArchive was introduced in PHP 5.2.0 (but, ZipArchive is also available as a PECL package).
In PHP 8 you can use ZipArchive::replaceFile
As demonstrated by this example from the docs:
<?php
$zip = new ZipArchive;
if ($zip->open('test.zip') === TRUE) {
$zip->replaceFile('/path/to/index.txt', 1);
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
?>
How would you go about reading odt files in PHP? I know you can use QueryPath, but that seems a bit of an overkill,.. I just want to read the file.
odt, files are zip compressed xml.
If all you need to do is read the file raw. Just unzip it and read it like a normal file.
If you need to parse out usable text, then enters the need for QueryPath or some other xslt parser.
OpenTBS is able to read and modify OpenDocument files in PHP.
Since OpenDocument files are XML files stored into a zip archive, you can also use the TbsZip class to simply read a zip archive under PHP without any other library dependency.
/*Name of the document file*/
$document = 'Template.odt';
/**Function to extract text*/
function extracttext($filename) {
$dataFile = "content.xml";
//Create a new ZIP archive object
$zip = new ZipArchive;
// Open the archive file
if (true === $zip->open($filename)) {
// If successful, search for the data file in the archive
if (($index = $zip->locateName($dataFile)) !== false) {
// Index found! Now read it to a string
$text = $zip->getFromIndex($index);
// Load XML from a string
// Ignore errors and warnings
$xml = new DOMDocument;
$xml->loadXML($text, LIBXML_NOENT | LIBXML_XINCLUDE | LIBXML_NOERROR | LIBXML_NOWARNING);
// Return XML
return $xml->saveXML();
}
//Close the archive file
$zip->close();
}
// In case of failure return a message
return "File no`enter code here`t found";
}
echo extracttext($document);
http://pear.php.net/package/OpenDocument may be what you need. Haven't used it myself, though.