While loop error when uploading $_FILES - php

I'm looking to upload multiple files to a folder once all of the conditions are met successfully. I'm allowing the user to choose how many files they'd like to upload, however am receiving this error from the script:
Notice: Undefined offset: 1 in C:\xampp\htdocs\FreeCheese\news_parse.php on line 54
Note:
The number following 'Undefined offset:', in this case is set to '1'. When I chose to insert more file fields into the page this number becomes whatever the number of current file fields are being read by the PHP.
EG: I have three file fields, the error would then become:
Notice: Undefined offset: 3 in C:\xampp\htdocs\FreeCheese\news_parse.php on line 54
If I do select three files to upload, all of them are being correctly inserted into the folder, so I have no idea why I am being given an error when it is functioning as it should.
If anyone could help me fix this error then it'd be much appreciated.
Thanks in advance, Rich
Here is my code:
// Set the array object to 0 when entering the loop.
$i = 0;
while ($_FILES['upload1']['tmp_name'][$i]) {
$imgName1 = preg_replace("#[^a-z0-9.]#i", "", $_FILES['upload1']['name'][$i]);
// Applies a unique number before the file name to prevent files from overwriting.
$imgName1 = mt_rand(100000, 999999).$imgName1;
// Moves the image into the images/ folder
move_uploaded_file($imgTmp1[$i], "images/$imgName1");
// Sets the next array object in the loop to 1 etc etc
$i ++;
}

If there are 5 files, then $_FILES['upload1']['tmp_name'][5] won't exist, so the while condition crashes (it doesn't return false !)...
You have to check count($_FILES['upload1']['tmp_name']) !
$nbFiles = count($_FILES['upload1']['tmp_name']);
while ($i < $nbFiles) {
[...your code...]
$i++;
}
You should also use a for loop, since it is made for what you need :
$nbFiles = count($_FILES['upload1']['tmp_name']);
for ($i=0; $i < $nbFiles; $i++) {
[...your code...]
}

Related

How do I read first line from a text file validate and then read the rest of the file in to an array?

I have a problem with the reading and validating some files(.txt). What I am trying to do is to read the first line from the text which has 4 columns: a module name, a title name, a teacher name and a date. I need to take this first line to convert into a string and validate each column. After validation to continue to read the file on the next line which it has 2 columns one for id and one for marks. I need to take the second line as well and validate the id and the marks.
The text files are in this format. Some of them are missing the date or the name.
DT1617T1, Problem Solving for Programming , Gordon MacIntyre , 20/05/2016
12345678, 56
34567822, 67
12324654, 98
234769O1, 45
12563792, 49
74537299, 7I
99834511, 50
77625489, 56
55274559, 63
22009643, 71
72578129, 51
I got stuck and I don't know how to read the first line validate and then read the rest from second line. I have to do all this in a loop to read multiple files. I managed to read and validate the first line appart of the date cause I don't know how to do that as well. But now I need to start reading from the second line without the first line.
This is one of my projects for school I just started as a programmer and if anyone can help me, please.
<?php
function sorting(){
$dataFolder = 'data';
// checking if directory with the name 'data' exists
if(is_dir($dataFolder)){
$textFiles = glob("$dataFolder/*.txt"); //extracting the files with the extension .txt
$i=0;//counter for the files array;
$errorCount=0;//counting error in the first line of text;
//sorting the .txt files and extracting the first line from file
foreach($textFiles as $files){ //looping trought the folder and extracting all the files with extension .txt
$codeLines = fopen($files, "r");//opening the files
$fileContets=file_get_contents($files);//getting all content of the file for validation
$fLine=fgets($codeLines) ;//reading the files
$fLine=explode("," , $fLine);//storring the first line of text as an array
fclose($codeLines);//closing the file
//validation function
if(filesize($files) == 0 or $fileContets == "" ){ echo "<p>Ups the file is empty</p>";}
$moduleCode = $fLine[0]; //first item in the array $fLine
$moduleTitle = $fLine[1]; //second item in the array $fLine
$tutorName = $fLine[2]; //third item in the array $fLine
$dateMarking = $fLine[3]; //forth item in the array $fLine
$errorLog="<p>Module Code: $moduleCode- ERROR Module code is incorect</p>"; //error code
$x = "<p>Module Code: $moduleCode </p>";// no error
echo "<p>File name: $textFiles[$i] </p>"; // echo the file name that is currently itterate
$i++;
if (!preg_match('/^(PP|P1|DT)[\d]{4}T[123]/' , $moduleCode)) {
$errorCount++;
echo $errorLog; }
else
{echo " <p>Module Code: $moduleCode </p>" ; }
if($moduleTitle == "")
{echo "<p>Title: ERROR - Title is missig </p>"; $errorCount++;}
else
{echo "<p>Title: $moduleTitle </p>"; }
if($tutorName == "")
{echo "<p>Tutor Name: ERROR - Tutor name is missing </p>"; $errorCount++;}
else
{echo "<p>Tutor Name: $tutorName</p>";}
$handle = fopen($files , 'r');
while (!feof($handle)) {
$name = fgets($handle, 1024);
echo '<p>' . $name . '</p>'; }
}
echo"<p>Numbers of errors on file is : `enter code here`$errorCount</p>";
}
}
sorting();
?>
The easiest way would be to open the file, read the first line - validate, if that is valid then read each line after till end of file and validate these lines. Also use fgetcsv() to read the file, it gives you an array of the fields in the file without having to use explode().
You may be better off with more of a structure like...
foreach($textFiles as $files){ //looping trought the folder and extracting all the files with extension .txt
$codeLines = fopen($files, "r");//opening the files
$fLine=fgetcsv($codeLines) ;//reading the files
// Validate the 1st line
if ( !$valid ) {
fclose ( $codeLines );
continue; // Skip rest of read
}
while ( !feof($codeLines) ) { // Loop to end of file
$fLine = fgetcsv($codeLines) ;
// Validate the rest of the lines
}
fclose ( $codeLines ); // When finished close the file

How to eliminate "Notice: Undefined offset: 1" errors while importing data from CSV file

In this code today I am trying to update data in bulk. User uploads a CSV file, the system checks if the file type is correct, then fetches the data and updates the data accordingly with the help of a WHILE loop. Have a look at the code below.
if(isset($_POST['upload'])) {
if($_FILES['theFile']['name']) {
$filename = explode(".", $_FILES['theFile']['name']);
if(end($filename) == "csv") {
$handle = fopen($_FILES['theFile']['tmp_name'], "r");
while($file_data = fgetcsv($handle)) {
$id = $DBcon->real_escape_string($file_data[0]);
$newdate = $DBcon->real_escape_string($file_data[1]);
$newdate = strtotime($newdate);
$newdate = date('Y-m-d', $newdate);
$query = "UPDATE IGNORE products SET expirydate='".$newdate."' WHERE id='".$vc."'";
if ($DBcon->query($query)) {
$serror = "Customer Updatation Successful";
} else {
$error = "Something Went Wrong - Contact Support";
}
}
fclose($handle);
$serror = "Successfully Fetched Details";
} else {
$error = "Please select a CSV file";
}
} else {
$error = "Please select a CSV file";
}
}
The thing is everything works fine until we follow the rules. Let's have a look into the CSV file that works just fine.
123,11-06-2019
124,11-06-2019
125,11-06-2019
126,11-06-2019
127,11-06-2019
But when the CSV output does not includes a " , " between the columns it throws unwanted error.
Here's the CSV file example
123 11-06-2019
124 11-06-2019
125 11-06-2019
126 11-06-2019
127 11-06-2019
Getting this error:
Okay
Notice
: Undefined offset: 1 in
D:\server\filepath\htdocs\filename.php
on line
21
Screenshot:
http://prntscr.com/o4r9vi
The line 21 defines the next column in this case.
$newdate = $DBcon->real_escape_string($file_data[1]);
What can be done in this case to avoid/fix the error? I was thinking to throw an error when the file content does not meets certain requirements, such as when the file does not contains certain number of commas defining all the required/expected columns. But how can I do that exactly? I am pretty new to this part of PHP.
Thank you for your time.
You can start simply by doing a count on your $file_data variable to ensure that the number of fields you expect exist. You could also go further and check that the type of data you expect is valid. There is a library to do this called CSVUtils. Effectively the best all round approach is to first lint the CSV to ensure it conforms to RFC 4180. It should also be noted that there are issues with respect to PHPs fputcsv so if the CSVs are being generated by PHP in the first place linting could be an issue in some instances. To add to this if you wanted you could even check the mime type of the file first and also turn your notices into an exception. The solution to this can be found here.
Example of count.
if (count($file_data) < 2) {
// do something (e.g. fill error array or throw exeption)
}

php - for loop repeating itself / going out of sequence

I'm very new to PHP, making errors and learning as I go. Please be gentle! :)
I want to access some data from Blizzard.com's API. For this particular data set, it's not a block of data in JSON, rather each object has it's own URL to access. I estimate that there are approx 150000 objects, however I don't know the start or end points of the number range. So I'm having to assume 1 and work past the highest number I know (269065)
To get the data, I need to access each object's data via a JSON file, which I read, get the contents of & drop in to a text file (this could be written as an insert in to a SQL db too, as I'm able to do this if it's the text file that's the issue). But to be honest, I would love to get to the bottom of why this is happening as much as anything!
I wasn't going to try and run ~250000 iterations in a for loop, I thought I'd try something I considered small, 2000.
The for loop starts with $a as 1, uses $a as part of the URL, loads & decodes the JSON, checks to see if the first field (ID) in the object is set, if it is, it writes a few fields to data.txt & if the first field (ID) isn't set it just writes $a to data.txt (so I know it's a null for other purposes not outlined here).
Simple! Or so I thought, after approx after 183 iterations, the data written to the text file goes awry as seen by the quote below. It is out of sequence and starts at 1 again, then back to 184 ad nauseam. The loop then seems to be locked in some kind of infinite loop of running, outputting in a random order until I close the page 10-20 minutes later.
I have obviously made a big mistake! But I have no idea what I have done wrong to have caused this. During my attempts I have rewritten the code with new variable names, so a new text does not conflict with code that could be running in memory.
I've tried resetting variables to blank at the end of the loop in case it something was being reused that was causing a problem.
If anyone could point out any errors in my code, or suggest something for me to look in to, to handle bigger loops that would be brilliant. I am assuming my issue may be a time out or memory problem. But I don't know where to start & was hoping I'd find some suggestions here.
If it's relevant, I am using 000webhostapp.com as my host provider for now, until I get some paid for hosting.
1 ... 182 183 1 184 2 3 185 4 186 5 187 6 188 7 189 190 8 191
for ($a = 1; $a <= 2000; $a++) {
$json = "https://eu.api.battle.net/wow/recipe/".$a."?locale=en_GB&<MYPRIVATEAPIKEY>";
$contents = file_get_contents($json);
$data = json_decode($contents,true);
if (isset($data['id'])) {
$file = fopen("data.txt","a");
fwrite($file,$data['id'].",'".$data['name']."'\n");
fclose($file);
} else {
$file = fopen("data.txt","a");
fwrite($file,$a."\n");
fclose($file);
}
}
The content of the file I'm trying to access is
{"id":33994,"name":"Precise Strikes","profession":"Enchanting","icon":"spell_holy_greaterheal"}
I scrapped the original plan and wrote this instead. Thank you again who took the time out of their day to help and offer suggestions!
$b = $mysqli->query("SELECT id FROM `static_recipes` order by id desc LIMIT 1;")->fetch_object()->id;
if (empty($b)) {$b=1;};
$count = $b+101;
$write = [];
for ($a = $b+1; $a < $count; $a++) {
$json = "https://eu.api.battle.net/wow/recipe/".$a."?locale=en_GB&apikey=";
$contents = #file_get_contents($json);
$data = json_decode($contents,true);
if (isset($data['id'])) {
$write [] = "(".$data['id'].",'".addslashes($data['name'])."','".addslashes($data['profession'])."','".addslashes($data['icon'])."')";
} else {
$write [] = "(".$a.",'a','a','a'".")";
}
}
$SQL = ('INSERT INTO `static_recipes` (id, name, profession, icon) VALUES '.implode(',', $write));
$mysqli->query($SQL);
$mysqli->close();
$write = [];
for ($a = 1; $a <= 2000; $a++) {
$json = "https://eu.api.battle.net/wow/".$a."?locale=en_GB&<MYPRIVATEAPIKEY>";
$contents = file_get_contents($json);
$data = json_decode($contents,true);
if (isset($data['id'])) {
$write [] = $data['id'].",'".$data['name']."'\n";
} else {
$write [] = $a."\n";
}
}
$file = fopen("data.txt","a");
fwrite($file, implode('', $write));
fclose($file);
Also, why you are think what some IDS isn't duplicated at several "https://eu.api.battle.net/wow/[N]" urls data?
Also if you are I wasn't going to try and run ~250000 think about curl_multi_init(): http://php.net/manual/en/function.curl-multi-init.php
I can't really see anything obviously wrong with your code, can't run it though as I don't have the JSON
It could be possible that there is some kind of race condition since you're opening and closing the same file hundreds of times very quickly.
File operations might seem atomic but not necessarily so - here's an interesting SO thread:
Does PHP wait for filesystem operations (like file_put_contents) to complete before moving on?
Like some others' suggested - maybe just open the file before you enter the loop then close the file when the loop breaks.
I'd try it first and see if it helps.
There's nothing in your original code that would cause that sort of behaviour. PHP will not arbitrarily change the value of a variable. You are opening this file in append mode, are you certain that you're not looking at old data? Maybe output some debug messages as you process the data. It's likely you'd run up against some rate limiting on the API server, so putting a pause in there somewhere may improve reliability.
The only substantive change I'd suggest to your code is opening the file once and closing it when you're done.
$file = fopen("data_1_2000.txt", "w");
for ($a = 1; $a <= 2000; $a++) {
$json = "https://eu.api.battle.net/wow/recipe/$a?locale=en_GB&<MYPRIVATEAPIKEY>";
$contents = file_get_contents($json);
$data = json_decode($contents, true);
if (!empty($data['id'])) {
$data["name"] = str_replace("'", "\\'", $data["name"]);
$record = "$data[id],'$data[name]'";
} else {
$record = $a;
}
fwrite($file, "$record\n");
sleep(1);
echo "$a "; if ($a % 50 === 0) echo "\n";
}
fclose($file);

Looping through files, one file processes, then that's it, no error reporting

So I have a problem with a script I'm working on. I have a folder full of JSON files called roster0.json, roster1, etc. etc.
$dir = "responses/";
$files = glob($dir . "roster*");
$failed = array();
$failcnt = 0;
if (isset($files)) {
$data = null;
for ($i = 0; $i < count($files); $i++) {
$data = json_decode(utf8_decode(file_get_contents($files[$i])));
if(isset($data)){
// Process stuff
When I var_dump($files) I get an array with over 100 paths "responses/roster0.json".
When I test $data I get a proper array of data.
However, once the loop goes to the next file, it never loads it, and never processes it.
Here's the crazy part. If I change the start of the for loop, e.g. $i = 20. It will load the 21st file in the directory and parse it and insert it into the db properly!
Ignoring the failcnt stuff at the bottom, here's the current version of the script in it's entirety. http://pastebin.com/yqyKi5Ag
PS - I have full WARNING/ERROR reporting on in PHP and not getting any error messages...HELP! Thanks!
When I was writing the insert string the ID was being duplicated and thus was invalid. Switched to auto-inc and tada. It works. Thanks for the assistance. –

How do I increment a variable so it chooses differnet lines from a text files in a While Loop

I have a script im writing. Here is whats happening. There is a while loop. In the while loop is a variable which is constant to X. How do i make X change from line one, line two, etc for each cycle of the while loop and pull X from a .txt file. Everything is in root. Thanks
$f = fopen("some.txt", "r");
while (!feof($f) && $some_condition) {
$x = fgets($f);
// do something
}
fclose($f);
Would this be sufficient?
Here is the pseudo code captain Kirk:
//we assume current working directory is root
fileHandle = openFile("Read","some.txt");
X = pull("X",fileHandle);
while( X is constant )
{
XFactor = factor(X);
}
I can refine and improve this with more details about what universe you are from, the programming language you intend to use, and more specifics about what you want to happen.
//get the lines of the file into an array
$file_array = file($file_name);
//go through the array line by line
foreach ($file_array as $line_number => $line)
{
//you didn't tell us what you are doing with each line
//so you will need to change this to your liking
$X = $line; // Handle the line
}
Edit: Note for very large files this may not be a good approach because this will load the entire file into memory at one time.

Categories