PHP ZipArchive stopped working - php

I have a script which takes a zipped CSV file, unzips it, and removes duplicate entries. It was mostly working, until I moved the unzip code into a function. Now it fails to unzip the .zip file, but doesn't show an error.
Checked file/folder permissions, everything is 777 on dev machine.
<?php
//
//huge memory limit for large files
$old = ini_set('memory_limit', '8192M');
//
//create a string like the filename
$base_filename = 'csv-zip-file'.date('m').'_'.date('d').'_'.date('Y');
//
//if the file exists ...
//unzip it
//read it to an array
//remove duplicates
//save it as a new csv
if (file_exists($base_filename.'.zip')) {
$zip_filename = $base_filename.'.zip';
echo "The file <strong>$zip_filename</strong> exists<br>";
unzip($zip_filename);
$csv = csv_to_array();
$csv = unique_multidim_array($csv,"Project Id");
var_dump($csv);
} else {
echo "The file <strong>$base_filename.zip</strong> does not exist";
}
function unzip($file_to_unzip) {
$zip=new ZipArchive();
if($zip->open($file_to_unzip)==TRUE) {
$address=__DIR__;
$zip->extractTo($address);
$res=$zip->close();
echo 'ok';
}
else{
echo 'failed';
}
}
function unique_multidim_array($array, $key) {
$temp_array = array();
$i = 0;
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
function csv_to_array () {
// global $filename;
global $base_filename;
$rows = array_map('str_getcsv', file($base_filename.'.csv'));
//using array_pop to remove the copyright on final row
array_pop($rows);
$header = array_shift($rows);
$csv = array();
foreach ($rows as $row) {
$csv[] = array_combine($header, $row);
}
return $csv;
}

Interesting problem you have here.
Output $file_to_unzip right inside the function.
Does $zip->* have an last_error or last_response method? See
what the ZipArchive class IS returning.
Do you have access to the php error logs? Let's look there for any output.

Related

php copy file for each filename in array

I am trying to move all the files in my array from one directory to another.
I have done some research and are using the php Copy() function.
here is my code so far:
$filenameArray = "img1.png,img2.png,img3.png";
$sourcePath = "/source/";
$savePath = "/newDir/";
$myArray = explode(',', $filenameArray);
$finalArray = print_r($myArray);
function copyFiles($finalArray,$sourcePath,$savePath) {
for($i = 0;$i < count($finalArray);$i++){
copy($sourcePath.$finalArray[$i],$savePath.$finalArray[$i]);}
}
Anyone see where I'm going wrong?
Thanks in advance!
This is the unlink ive been attempting to use.
function copyFiles($finalArray,$sourcePath,$savePath) {
foreach ($finalArray as $file){
if (!copy($sourcePath.$file,$savePath.$file)) {
echo "Failed to move image";
}
$delete[] = $sourcePath.$file;
}
}
// Delete all successfully-copied files
foreach ( $delete as $file ) {
unlink( $sourcePath.$file );
}
My Final Working Code
the code below moves images in comma seperated array to new folder and removes them from current folder
$finalArray = explode(',', $filenameArray);
function copyFiles($finalArray,$sourcePath,$savePath) {
foreach ($finalArray as $file){
if (!copy($sourcePath.$file,$savePath.$file)) {
echo "Failed to move image";
}
}
}
copyFiles( $finalArray, $sourcePath, $savePath);
function removeFiles($finalArray,$sourcePath) {
foreach ($finalArray as $file){
if (!unlink($sourcePath.$file)) {
echo "Failed to remove image";
}
}
}
removeFiles( $finalArray, $sourcePath);
In your code you are not calling the copyFile function. Try this:
$filenameArray = "img1.png,img2.png,img3.png";
$sourcePath = "/source/";
$savePath = "/newDir/";
$finalArray = explode(',', $filenameArray);
function mvFiles($finalArray,$sourcePath,$savePath) {
foreach ($finalArray as $file){
if (!rename($sourcePath.$file,$savePath.$file)) {
echo "failed to copy $file...\n";
}
}
}
mvFiles( $finalArray, $sourcePath, $savePath);
A simple solution :
$filenameArray = "img1.png,img2.png,img3.png";
$sourcePath = "/source/";
$savePath = "/newDir/";
$myArray = explode(',', $filenameArray);
$finalArray = $myArray; //corrected this line
function copyFiles($finalArray, $sourcePath, $savePath)
{
for ($i = 0; $i < count($finalArray); $i++)
{
copy($sourcePath.$finalArray[$i],$savePath.$finalArray[$i]);
}
}
Hope you have right call to function copyFiles().
UPDATE for unlink() :
Let me try to throw some light on your work (written code):
foreach ($finalArray as $file)
{
if (!copy($sourcePath.$file,$savePath.$file))
{
echo "Failed to move image";
}
$delete[] = $sourcePath.$file;
}
Contents of $delete :
a. /source/img1.png
b. /source/img2.png
c. /source/img3.png
Now,
foreach ( $delete as $file )
{
unlink( $sourcePath.$file );
}
unlink() will be called with the following parameters:
$sourcePath.$file : /source/./source/img1.png : /source//source/img1.png => No such path exists
$sourcePath.$file : /source/./source/img2.png : /source//source/img2.png => No such path exists
$sourcePath.$file : /source/./source/img3.png : /source//source/img3.png => No such path exists
$sourcePath.$file : /source/./source/img4.png : /source//source/img4.png => No such path exists
I think for this reason, unlink is not working.
The code to be written should be like the following:
foreach ( $delete as $file )
{
unlink( $file );
}
Now, unlink() will be called with the following parameters:
a. /source/img1.png => path do exists
b. /source/img2.png => path do exists
c. /source/img3.png => path do exists
Do tell me if this does not solves the issue.
Update as per Dave Lynch's code:
$filenameArray = "img1.png,img2.png,img3.png";
$sourcePath = "/source/";
$savePath = "/newDir/";
$finalArray = explode(',', $filenameArray);
foreach ($finalArray as $file)
{
$delete[] = $sourcePath.$file;
}
foreach ( $delete as $file )
{
echo $sourcePath.$file . "</br>";
}
Output:
/source//source/img1.png
/source//source/img2.png
/source//source/img3.png
Please check.
Thanks and Regards,

Using PHP to display items on page

I have a document called subjects.txt in the following format:
DateCreated,Subject,Link
18.10.2015,"Math",http: //address.html
17.10.2015,"English",http: //address.html
18.10.2015,"English",http: //address.html
19.10.2015,"Science",http: //address.html
17.10.2015,"Math",http: //address.html
The file contains URLs of sites created based on a school subject. There can be more than one site for a subject.
The goal is to use PHP to open, read, and display the contents of the file in the following format:
Math
Link 1
Link 2
English
Link 1
Link 2
Science (because there's only one link, the name of the subject is the
link)
So far I've been able to open and read the file:
$file = "./subjects.txt";
$subjects = file_get_contents($file);
I'm having trouble trying to determine how to go about writing the file in specified format.
I've tried using explode to separate the elements with "," - however I don't know where to go from there.
Your input file looks to be in Comma-separated values (CSV) format. PHP has a built-in fgetcsv function designed to make reading CSV data from a file easy.
<?php
$file = './subjects.txt';
$fh = fopen($file, 'r');
if ($fh === false) {
die("Can not read {$file}");
}
$data = array();
while (($row = fgetcsv($fh, 1000, ',')) !== false) {
if ($row[0] === 'DateCreated') {
// Ignore the column header row
continue;
}
list($date, $subject, $link) = $row;
if (!isset($data[$subject])) {
$data[$subject] = array();
}
$data[$subject][] = $link;
}
fclose($fh);
foreach ($data as $subject => $links) {
// TODO: output each subject here
}
Here is another version
<?php
$file = "./subjects.txt";
$h = fopen($file, "r");
if($h !== false) {
$subjects = [];
$data = [];
while(!feof($h)) {
if($line = trim(fgets($h))) {
$line = explode(",", $line);
if(!in_array("DateCreated",$line)) {
array_push($subjects, $line);
}
}
}
fclose($h);
foreach ($subjects as $subject) {
if(!isset($data[$subject[1]])) {
$data[$subject[1]] = [];
}
$data[$subject[1]][] = $subject[2];
}
foreach ($data as $subject => $links) {
if(count($links) == 1) {
echo "<p>$subject</p>\n";
} else {
$i = 1;
echo "<p>$subject</p>\n";
echo "<ul>\n";
foreach ($links as $link) {
echo "<li>link$i</li>\n";
$i++;
}
echo "</ul>\n";
}
}
}
?>
The problem using file_get_contents() is that retrieves all the file contents into $subjects.
You have to use a different approach. For example fgets():
$fp = fopen("./subjects.txt", "r");
if ($fp){
while (($line = fgets($fp)) !== false){
// So here you can treat each line individually.
// You can use explode (";", $line) for example if the line is not empty
}
}
fclose($fp);
Using fgets() will allow you to parse each of the file's lines individually.
As stated doing this with a database would be much easier probably 3 lines of code. Here's one approach you could use though.
$data = '18.10.2015,"Math",http: //address.html
17.10.2015,"English",http: //address1.html
18.10.2015,"English",http: //address2.html
19.10.2015,"Science",http: //address3.html
17.10.2015,"Math",http: //address4.html';
preg_match_all('~^(.*?),"(.*?)",(.*?)$~m', $data, $fields);
array_multisort($fields[2], SORT_STRING, $fields[1], $fields[3]);
$lastcat = '';
foreach($fields[2] as $key => $cat) {
if($cat != $lastcat) {
echo $cat . "\n";
}
$lastcat = $cat;
echo $fields[3][$key] . "\n";
}
Output:
English
http: //address1.html
http: //address2.html
Math
http: //address4.html
http: //address.html
Science
http: //address3.html
The array_multisort is how the categories are grouped.
Here's a regex101 demo of what that regex is doing. https://regex101.com/r/wN3nB2/1
Update for single record check (only ran 1 test on it):
$data = '18.10.2015,"Math",http: //address.html
17.10.2015,"English",http: //address1.html
18.10.2015,"English",http: //address2.html
19.10.2015,"Science",http: //address3.html
17.10.2015,"Math",http: //address4.html';
preg_match_all('~^(.*?),"(.*?)",(.*?)$~m', $data, $fields);
array_multisort($fields[2], SORT_STRING, $fields[1], $fields[3]);
$lastcat = '';
foreach($fields[2] as $key => $cat) {
if((empty($fields[2][($key +1)]) && $cat != $lastcat)|| ($cat != $lastcat && !empty($fields[2][($key +1)]) && $fields[2][($key +1)] != $cat)) {
//single record
echo $cat . $fields[3][$key] . "\n";
} else {
if($cat != $lastcat) {
echo $cat . "\n";
}
$lastcat = $cat;
echo $fields[3][$key] . "\n";
}
}

Method to speed up reading the contents of a file

In a script I'm having I'm pulling a csv from a remote server using ftp. I save this file locally and then open the file. I loop through all the contents of the file matching a certain value against it. If it matches, the script can continue.
Enough talking. Lets show some code...
$filename = 'ftp://.....';
$localCsv = '/tmp/'.date('Ymd').'.csv';
if (!file_exists($localCsv)) {
$content = file_get_contents($filename);
file_put_contents($localCsv, $content);
}
Now that we have the file created. We can continue to loop.
$handle = fopen($localCsv, "r");
while(!feof($handle)) {
$rows[] = fgets($handle);
}
fclose($handle);
$results = array();
foreach ($rows as $rid => $row) {
$columns = explode("\t", $row);
$results[$columns[2]] = $columns;
}
if (array_key_exists($searchValue, $results)) {
... Continue script ...
}
There is just one tiny little problem with this method. It's so slow it's almost going backwards.
Heres all baked together, maybe thats faster?
$handle = fopen($localCsv, "r");
$results = array();
while(!feof($handle)) {
$columns = explode("\t", fgets($handle));
$results[$columns[2]] = $columns;
if ($columns[2] == $searchValue) {
//SEARCH HIT
}
}
fclose($handle);
If thats not working you could try the csv-specific methods that are in PHP

Reading a File Name with PHP

I'm writing a news script, and I'm having trouble making a way for the files to be deleted.
How can I change this script so that the <input type="checkbox" /> has a value of the file in the same row?
<?php
// This function reads all available news
function getNewsList(){
$fileList = array();
// Open the actual directory
if ($handle = opendir("news")) {
// Read all file from the actual directory
while ($file = readdir($handle)) {
if (!is_dir($file)) {
$fileList[] = $file;
}
}
}
rsort($fileList);
return $fileList;
}
// new
$list = getNewsList();
print("<table>\n");
print("<tr><td> </td><td>Article Title:</td><td>Post Date:</td></tr>\n");
foreach ($list as $value) {
$newsData = file("news/".$value);
$newsTitle = $newsData[0];
$submitDate = $newsData[1];
unset ($newsData['0']);
unset ($newsData['1']);
$newsContent = "";
foreach ($newsData as $value) {
$newsContent .= $value;
}
print("<tr>");
print("<td><input type=\"checkbox\" name=\"check_files[]\" value=\"$file\" /></td>");
print("<td>$newsTitle</td>");
print("<td>");
print("$submitDate");
print("</td>");
print("</tr>\n");
}
print("</table>\n");
I have a similar script for managing files, and it's something like $dirArray[$index] for the file name, but I can't figure out how to adapt this script to work the same way, because I'm too new to PHP.
Thanks for the help!
EDIT: This is the line where the file name needs to be: (instead of $file, which doesn't work for some reason):
print("<td><input type=\"checkbox\" name=\"check_files[]\" value=\"$file\" /></td>");
The $file variable isn't defined anywhere, you could try this:
replace
$newsData = file("news/".$value);
with
$file="news/".$value;
$newsData = file($file);
In your script, it looks like the current file name is stored in $value, because $list = getNewsList(); is an array of filenames, and your doing a foreach on it : foreach ($list as $value) {
Try replacing the second foreach loop with:
foreach ($newsData as $content) {
$newsContent .= $content;
}
and then use this line to show the file:
print("<td><input type=\"checkbox\" name=\"check_files[]\" value=\"$value\" /></td>");

Problem with the fgetcsv() in php

I have the following piece of code to parse a csv file. After that I am displaying it. The .csv file is displaying perfectly on my local machine but on the server after clicking on upload a blank page is displaying.
function uploadTrainees()
{
$csv = array();
$tmpName = $_FILES['csv']['tmp_name'];
//echo $tmpName;
//ini_set('auto_detect_line_endings',true);
$fp = fopen($tmpName,'r');
$fields = array('delegate_title', 'delegate_firstname', 'delegate_lastname', 'delegate_jobtitle', 'delegate_email', 'delegate_phone', 'is_bringing_own_laptop');
$records = array();
while ($record = fgetcsv($fp,1000,','))
{
$records[] = array_combine($fields, $record);
}
fclose($fp);
}
Help me to solve this issue.
What version of PHP is the live server running?
The function array_combine() is only in PHP5
Edit
There is a function here to do this - http://snipplr.com/view/4918/arraycombine-for-php4/
if (!function_exists('array_combine'))
{
function array_combine($arr1,$arr2) {
$out = array();
foreach ($arr1 as $key1 => $value1) {
$out[$value1] = $arr2[$key1];
}
return $out;
}
}

Categories