I'm creating a online widget creation tool in PHP, and I am able to export everything I need via .zip , just the problem is that users have to extract the zip and then add the .wdgt extension on the folder for it to work in iBooks. Is there any way I could make this part of the process easier, e.g - just unzip and the .wdgt folder is there, or even better, download as .wdgt.
Here is the code I have to create a ZIP file:
//zip name
$archiveName = 'widget.zip';
$fileNames = array();
//scan through directories, and add to array
foreach(scandir($workingDir) as $content){
$fileNames[] = $workingDir.$content;
}
foreach(scandir($resources) as $content){
$fileNames[] = $resources.$content;
}
archiveFiles($fileNames, $archiveName);
function archiveFiles($fileNames, $archiveName){
//init new ZipArchive()
$zip = new ZipArchive();
//open archive
$zip->open($archiveName);
if($zip->open($archiveName, ZIPARCHIVE::OVERWRITE ) !==TRUE){
exit("Cannot open <$archiveName>\n");
}
else{
//archive create, now add files
foreach($fileNames as $files){
if('.' === $files || '..' === $files) continue;
//get just the filename and extension
$fileName = explode("/", $files);
$num = (count($fileName) - 1);
$theFilename = $fileName[$num];
//add file into the archive - full path of file, new filename
$zip->addFile($files,$theFilename);
}
$zip->close();
header( 'Location: http://MYURL/'.$archiveName ) ; //Redirects to the zip archive
exit;
}
}
This works fine. I just need to be able to either just download a .wdgt folder with the content I need in it, or be able to ZIP up a .wdgt folder that has the content that I need.
I have tried changing $archiveName to $archiveName = "widget.wdgt.zip"; and $archiveName = "widget.wdgt";
The $archiveName = "widget.wdgt.zip"; was able to unzip fine on Windows. Although on the MAC is just gave an error. And It has to work on the MAC as it is in iBook's Author these widgets will work on
Managed to get a .wdgt folder downloaded within a zip file, all that I needed to do was when adding the file in the loop was this:
$zip->addFile($files, 'MYWIDGET.wdgt/'.$theFilename);
by adding the 'MYWIDGET.wdgt/'.$theFilename path into the addFile() it forced ZipArchive to create a MYWIDGET.wdgt folder and adding the files into it.
Related
I'm struggling around with a simple PHP functionality: Creating a ZIP Archive with some files in.
The problem is, it does not create only one file called filename.zip but two files called filename.zip.a07600 and filename.zip.b07600. Pls. see the following screenshot:
The two files are perfect in size and I even can rename each of them to filename.zip and extract it without any problems.
Can anybody tell me what is going wrong???
function zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path = array(), $files_array = array()) {
// Archive File Name
$archive_file = $archiveDir."/".$archive_file_name;
// Time-to-live
$archiveTTL = 86400; // 1 day
// Delete old zip file
#unlink($archive_file);
// Create the object
$zip = new ZipArchive();
// Create the file and throw the error if unsuccessful
if ($zip->open($archive_file, ZIPARCHIVE::CREATE) !== TRUE) {
$response->res = "Cannot open '$archive_file'";
return $response;
}
// Add each file of $file_name array to archive
$i = 0;
foreach($files_array as $value){
$expl = explode("/", $value);
$file = $expl[(count($expl)-1)];
$path_file = $file_path[$i] . "/" . $file;
$size = round((filesize ($path_file) / 1024), 0);
if(file_exists($path_file)){
$zip->addFile($path_file, $file);
}
$i++;
}
$zip->close();
// Then send the headers to redirect to the ZIP file
header("HTTP/1.1 303 See Other"); // 303 is technically correct for this type of redirect
header("Location: $archive_file");
exit;
}
The code which calls the function is a file with a switch-case... it is called itself by an ajax-call:
case "zdl":
$files_array = array();
$file_path = array();
foreach ($dbh->query("select GUID, DIRECTORY, BASENAME, ELEMENTID from SMDMS where ELEMENTID = ".$osguid." and PROJECTID = ".$osproject.";") as $subrow) {
$archive_file_name = $subrow['ELEMENTID'].".zip";
$archiveDir = "../".$subrow['DIRECTORY'];
$files_array[] = $archiveDir.DIR_SEPARATOR.$subrow['BASENAME'];
$file_path[] = $archiveDir;
}
zipFilesAndDownload_Defect($archive_file_name, $archiveDir, $file_path, $files_array);
break;
One more code... I tried to rename the latest 123456.zip.a01234 file to 123456.zip and then unlink the old 123456.zip.a01234 (and all prior added .a01234 files) with this function:
function zip_file_exists($pathfile){
$arr = array();
$dir = dirname($pathfile);
$renamed = 0;
foreach(glob($pathfile.'.*') as $file) {
$path_parts = pathinfo($file);
$dirname = $path_parts['dirname'];
$basename = $path_parts['basename'];
$extension = $path_parts['extension'];
$filename = $path_parts['filename'];
if($renamed == 0){
$old_name = $file;
$new_name = str_replace(".".$extension, "", $file);
#copy($old_name, $new_name);
#unlink($old_name);
$renamed = 1;
//file_put_contents($dir."/test.txt", "old_name: ".$old_name." - new_name: ".$new_name." - dirname: ".$dirname." - basename: ".$basename." - extension: ".$extension." - filename: ".$filename." - test: ".$test);
}else{
#unlink($file);
}
}
}
In short: copy works, rename didn't work and "unlink"-doesn't work at all... I'm out of ideas now... :(
ONE MORE TRY: I placed the output of $zip->getStatusString() in a variable and wrote it to a log file... the log entry it produced is: Renaming temporary file failed: No such file or directory.
But as you can see in the graphic above the file 43051221.zip.a07200 is located in the directory where the zip-lib opens it temporarily.
Thank you in advance for your help!
So, after struggling around for days... It was so simple:
Actually I work ONLY on *nix Servers so in my scripts I created the folders dynamically with 0777 Perms. I didn't know that IIS doesn't accept this permissions format at all!
So I remoted to the server, right clicked on the folder Documents (the hierarchically most upper folder of all dynamically added files and folders) and gave full control to all users I found.
Now it works perfect!!! The only thing that would be interesting now is: is this dangerous of any reason???
Thanks for your good will answers...
My suspicion is that your script is hitting the PHP script timeout. PHP zip creates a temporary file to zip in to where the filename is yourfilename.zip.some_random_number. This file is renamed to yourfilename.zip when the zip file is closed. If the script times out it will probably just get left there.
Try reducing the number of files to zip, or increasing the script timeout with set_time_limit()
http://php.net/manual/en/function.set-time-limit.php
I am doing a backup module, I need to zip all the webapp folder, I use this method:
function agregar_zip($dir, $zip){
if (is_dir($dir)) {
if ($da = opendir($dir)) {
while (($archivo = readdir($da))!== false) {
if (is_dir($dir . $archivo) && $archivo!="." && $archivo!=".."){
agregar_zip($dir.$archivo . "/", $zip);
}elseif(is_file($dir.$archivo) && $archivo!="." && $archivo!=".."){
$zip->addFile($dir.$archivo, $dir.$archivo);
}
}
closedir($da);
}
}
}
$zip = new ZipArchive();
$dir = Yii::app()->basePath.'/../';
$rutaFinal="c:/xampp/htdocs/";
$archivoZip = "backup.zip";
if($zip->open($archivoZip,ZIPARCHIVE::CREATE)===true) {
agregar_zip($dir, $zip);
$zip->close();
#rename($archivoZip, "c:/xampp/htdocs/backup.zip");
if (file_exists($rutaFinal.$archivoZip)){
}else{
Yii::app()->params['errores'] = Yii::app()->params['errores']."</br>No se ha creado el ZIP con éxito.";
}
}
When I open the file.zip, I have this structure:
C:/->xampp->htdocs->mywebapp(Here is all I need)
But If I do "extract here" Its unzip the right content, but If I do with php it create a folder in destination called xampp, inside it htdocs, inside it mywebapp(With the right content).
I need to zip only the app folder not all the route. This way when I unzip with php only unzip app folder.
I think you need to remove the "/../" from this line
$dir = Yii::app()->basePath.'/../';
should be
$dir = Yii::app()->basePath;
There is better way to make zip with yii.
Yii has a zip extension.
Usage example from the docs above:
Introduce EZip to Yii. Add definition to CWebApplication config file (main.php)
'components'=>array(
...
'zip'=>array(
'class'=>'application.extensions.zip.EZip',
),
...
),
Now you can access EZip methods as follows:
$zip = Yii::app()->zip;
$zip->makeZip('./','./toto.zip'); // make an ZIP archive
var_export($zip->infosZip('./toto.zip'), false); // get infos of this ZIP archive (without files content)
var_export($zip->infosZip('./toto.zip')); // get infos of this ZIP archive (with files content)
$zip->extractZip('./toto.zip', './1/'); //
I'm writing a PHP script that archives a selected directory and all its sub-folders. The code works fine, however, I'm running into a small problem with the structure of my archived file.
Imagine the script is located in var/app/current/example/two/ and that it wants to backup everything plus its sub directories starting at var/app/current
When I run the script it creates an archive with the following structure:
/var/app/current/index.html
/var/app/current/assets/test.css
/var/app/current/example/file.php
/var/app/current/example/two/script.php
Now I was wondering how:
a) How can I remove the /var/app/current/ folders so that the root directory of the archive starts beyond the folder current, creating the following structure:
index.html
assets/test.css
example/file.php
example/two/script.php
b) Why & how can I get rid of the "/" before the folder var?
//Create ZIP file
$zip = new ZipArchive();
$tmpzip = realpath(dirname(__FILE__))."/".substr(md5(TIME_NOW), 0, 10).random_str(54).".zip";
//If ZIP failed
if($zip->open($tmpzip,ZIPARCHIVE::CREATE)!== TRUE)
{
$status = "0";
}
else
{
//Fetch all files from directory
$basepath = getcwd(); // var/app/current/example/two
$basepath = str_replace("/example/two", "", $basepath); // var/app/current
$dir = new RecursiveDirectoryIterator($basepath);
//Loop through each file
foreach(new RecursiveIteratorIterator($dir) as $files => $file)
{
if(($file->getBasename() !== ".") && ($file->getBasename() !== ".."))
{
$zip->addFile(realpath($file), $file);
}
}
$zip->close();
You should try with:
$zip->addFile(realpath($file), str_replace("/var/app/current/","",$file));
I've never used the ZipArchive class before but with most archiver application it works if you change the directory and use relative path.
So you can try to use chdir to the folder you want to zip up.
I'm a PHP novice and so looking for some advice on a PHP function i have created to use within a Wordpress installation.
As you can see from the code below, it runs when one of the admin's press 'Publish' on a pending post.
It takes a Zip file that has been uploaded by a user via Gravity Forms, then unzips ONLY .mp3 extensions. Re-zips and moves all the files to a new folder in our Amazon S3 directory.
The code is pieced together from my limited knowledge and some help along the way with questions on here.
So, here's what i ended up with:
add_action('pending_to_publish', 'unzip_to_s3');
function unzip_to_s3() {
global $post;
global $wpdb;
// Only run function if post is portfolio post type
if ('portfolio' == $post->post_type) {
// Set temp path
$temp_path = '../wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/tmp/';
// Get filename from Zip file
$file = get_post_meta($post->ID, 'file_url', true);
$zip_file = basename($file);
// Create full Zip file path
$zip_file_path = $temp_path.$zip_file;
// Generate unique name for temp sub_folder for unzipped files
$temp_unzip_folder = uniqid('temp_TMS_', true);
// Create full temp sub_folder path
$temp_unzip_path = $temp_path.$temp_unzip_folder;
// Make the new temp sub_folder for unzipped files
if (!mkdir($temp_unzip_path, 0755, true)) {
die('Error: Could not create path: '.$temp_unzip_path);
}
// Unzip files to temp unzip folder, ignoring anything that is not a .mp3 extension
$zip = new ZipArchive();
$filename = $zip_file_path;
if ($zip->open($filename)!==TRUE) {
exit("cannot open <$filename>\n");
}
for ($i=0; $i<$zip->numFiles;$i++) {
$info = $zip->statIndex($i);
$file = pathinfo($info['name']);
if(strtolower($file['extension']) == "mp3") {
file_put_contents($temp_unzip_path.'/'.basename($info['name']), $zip->getFromIndex($i));
} else {
$zip->deleteIndex($i);
}
}
$zip->close();
// Re-zip the unzipped mp3's and store new zip file in temp folder created earlier
$temp_unzip_path = $temp_unzip_path.'/';
$zip = new ZipArchive();
$dirArray = array();
$new_zip_file = $temp_unzip_path.$zip_file;
$new = $zip->open($new_zip_file, ZIPARCHIVE::CREATE);
if ($new === true) {
$handle = opendir($temp_unzip_path);
while (false !== ($entry = readdir($handle))) {
if(!in_array($entry,array('.','..')))
{
$dirArray[] = $entry;
$zip->addFile($temp_unzip_path.$entry,$entry);
}
}
closedir($handle);
} else {
echo 'Failed to create Zip';
}
$zip->close();
// Set Media bucket dir
$bucket_path = '../wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/mixtape2/';
// Generate unique name for sub_bucket
$sub_bucket = uniqid('TMS_', true);
// Create full sub_bucket path
$sub_bucket_path = $bucket_path.$sub_bucket;
// Make the new sub_bucket
if (!mkdir($sub_bucket_path, 0755, true)) {
die('Error: Could not create path: '.$sub_bucket_path);
}
// Move mp3's to new sub_bucket
// Get array of all source files
$files = scandir($temp_unzip_path);
// Identify directories
$source = $temp_unzip_path;
$destination = $sub_bucket_path.'/';
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// if move files is successful delete the original temp folder
if (rename($source.$file, $destination.$file)) {
rmdir($temp_unzip_path);
}
}
// Delete original Zip file
unlink($temp_path.$zip_file);
// Update Custom field for new Zip file location
update_post_meta($post->ID, 'file_url', 'http://themixtapesite.com/wp-content/uploads/gravity_forms/1-9e5dc27086c8b2fd2e48678e1f54f98c/2013/02/mixtape2/'.$sub_bucket.'/'.$zip_file);
}
}
Whilst this function does work, we're dealing with large files and so it does take a while to process...
What is happening is when the admin presses publish it triggers this function but the page just sits there until it's finished this function and then will continue. This function can take upto around 5 minutes to run.
I'm looking to optimise this function (in terms of code) but also see if there's a way i can run this in the background so that the admin can carry on with other things and not have to sit there waiting around.
Any help appreciated.
You may want to try to WP cron and schedule the task at that point so that it runs in the background. Here is some resources for that. the basic concept would go something like this.
if ( ! wp_next_scheduled( 'pending_to_publish' ) ) {
wp_schedule_single_event($timestamp,'pending_to_publish');
}
add_action('pending_to_publish', 'unzip_to_s3');
http://wpengineer.com/1908/use-wordpress-cron/
http://codex.wordpress.org/Category%3aWP-Cron_Functions
https://wordpress.stackexchange.com/questions/42694/run-a-cron-job-or-similar-in-the-background-of-wp-after-post-update-create
I am trying to create a web app using codeigniter which will be used over a home or office network. Now Im looking for a backup option which can be done from the web protal. For example, in my htdocs folder i have: App1, App2 etc.
i want to backup and download the App1 folder directly from the webapp which can be done from any client machine which is connected to the server. is it possible. if yes then can you please let me know how?
~muttalebm
sorry for the late reply. I found a quite easy and simple backup option builtin with codeigniter. Hope this helps someone
$this->load->library('zip');
$path='C:\\xampp\\htdocs\\CodeIgniter\\';
$this->zip->read_dir($path);
$this->zip->download('my_backup.zip');
i used the code directly from the view and then just called it using the controller.
~muttalebm
Basically what you want to do is zip the application folder and download it, fairly simple to do. Please check out:
Download multiple files as a zip folder using php
On how to zip a folder for download.
I you do not have that extension a simple command can be used instead, I assume you are running on Linux if not replace command with zip/rar Windows equivalent:
$application_path = 'your full path to app folder without trailing slash';
exec('tar -pczf backup.tar.gz ' . $application_path . '/*');
header('Content-Type: application/tar');
readfile('backup.tar.gz');
Note: Make every effort to protect this file from being accessed by unauthorized users otherwise a malicious user will have a copy of your site code including config details.
// to intialize the path split the real path by dot .
public function init_path($string){
$array_path = explode('.', $string);
$realpath = '';
foreach ($array_path as $p)
{
$realpath .= $p;
$realpath .= '/';
}
return $realpath;
}
// backup files function
public function archive_folder($source = '' , $zip_name ='' , $save_dir = '' , $download = false){
// Get real path for our folder
$name = 'jpl';
if($zip_name == '')
{
$zip_name = $name."___(".date('H-i-s')."_".date('d-m-Y').")__".rand(1,11111111).".zip";
}
$realpath = $this->init_path($source);
if($save_dir != '')
{
$save_dir = $this->init_path($save_dir);
}else{
if (!is_dir('archives/'))
mkdir('archives/', 0777);
$save_dir = $this->init_path('archives');
}
$rootPath = realpath( $realpath);
// echo $rootPath;
// return;
// Initialize archive object
$zip = new ZipArchive();
$zip->open($save_dir . '\\' . $zip_name, ZipArchive::CREATE | ZipArchive::OVERWRITE);
// Create recursive directory iterator
/** #var SplFileInfo[] $files */
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($rootPath),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
// Get real and relative path for current file
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($rootPath) + 1);
// Add current file to archive
$zip->addFile($filePath, $relativePath);
}
}
// Zip archive will be created only after closing object
$zip->close();
if($download){
$this->download($zip);
}
}