PHP - Frequent error on multiple images upload - php

I created a multiple image upload form (the images are stored in a folder, and the informations in a MySQL database). To the images are associated some informations, like a description, a name, etc.
Often, when I upload many images (like 3,4), one/two of them aren't uploaded, and an error message appears (An error has occurred while uploading the file). Then, if I retry to upload the image not uploaded, no error occurs. Sometimes it appends, sometimes not, and I don't understand what the problem is (I think it is not normal).
Here you can see my PHP code and also my HTML form:
When the user clicks on the input type="file", my code just creates another input and hides the old one (so that, if the user wants upload more files, those already uploaded are not deleted).
function boomFunction(obj) {
obj.style.display = 'none';
$(".upload-container").append("<input name='upload[]' type='file' multiple='multiple' id='upload' class='upload' onclick='boomFunction(this)' title='Carica un altro file!'>");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="result.php" method="post" enctype="multipart/form-data" class="form-inline" autocomplete="off" novalidate>
<div class="upload-container">
<input name="upload[]" type="file" multiple="multiple" id="upload" class="upload" required="required" aria-required="true" onclick="boomFunction(this)" title="Choose a file!">
</div><br>
<label>Subjects:</label>
<textarea type="text" id="argomenti" name="argomenti" required="required" aria-required="true" placeholder="Subjects..."></textarea><br>
<label for="anno">Year:</label>
<select id="anno" name="anno" required="required" aria-required="true">
<option value="" disabled selected>Choose year</option>
<option value="2016-2017">2016-2017</option>
<option value="2017-2018">2017-2018</option>
<option value="2018-2019">2018-2019</option>
</select><br>
<input type="submit" value="Carica i file" class="upload_button"><br><br><br>
</form>
Then, here is my result.php page.
<?php
$total = count(array_filter($_FILES['upload']['name'])); // Count the number of uploaded files
$timestamp = time();
if ($total==0) {
echo "<h2>You must upload at least one file.</h2>";
$uploadOk = 0;
} else {
for($i = 0; $i < $total; $i++) {
$tmpFilePath = $_FILES['upload']['tmp_name'][$i];
if ($tmpFilePath != '') {
$newFilePath = "./uploadFiles/" . $_FILES['upload']['name'][$i];
$nomeCompletoFile = basename($_FILES["upload"]["name"][$i]);
$target_file = "uploads/$nomeCompletoFile"; $uploadOk = 1;
$estensione = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
if($estensione != 'jpg' && $estensione != 'png' && $estensione != 'jpeg') {
echo "<h2>Just JPG e PNG files are allowed.</h2>";
$uploadOk = 0;
}
elseif (empty($_POST["argomenti"]) or empty($_POST["anno"])) {
echo "<h2>You cannot leave empty fields</h2>";
$uploadOk = 0;
} else {
$nomeFile = str_replace(".$estensione", '', $nomeCompletoFile);
$string = base64_encode(openssl_random_pseudo_bytes(15)); // Random 15 letters for the new file name
$id = rand(1, 100000); $nomeFinaleFile = 'uploads/'.$string.$id.'.'.$estensione;
if (move_uploaded_file($_FILES["upload"]["tmp_name"][$i], $nomeFinaleFile)) {
$argomenti = stripslashes(htmlspecialchars($_POST['argomenti']));
$anno = $_POST['anno'];
$mysqli = new mysqli('localhost', 'name', '', 'my_name');
$mysqli->query("INSERT INTO uploads (timestamp, file, argomenti, anno, nFile) VALUES ('$timestamp', '$nomeFinaleFile', '$argomenti', '$anno', '$i')");
echo "<h2>The file <i>$nomeFile</i> has been uploaded.</h2>";
} else echo "<h2>An error has occurred while uploading the file</h2>";
}
}
}
}
?>
There seems to be no mistakes, indeed sometimes all works correctly.
Any help will be appreciated

Use base64encode url safe
replace
$string = base64_encode(openssl_random_pseudo_bytes(15)); // Random 15 letters for the new file name
to
$string = rtrim(strtr(base64_encode(openssl_random_pseudo_bytes(15)), ['+' => '-', '/' => '_']), '=');

Related

Match indexes of two arrays in PHP to pair data

I am doing a form with multiple files upload, for each file input there is a title input and I want to match the title with the file in order to be able to rename the file with the title.
I don't know how to match indexes of the two arrays to be able to do this.
Could someone help me? Thx
Here is my code so far ...
PHP :
$target_dir = 'files/';
if(isset($_POST['title']) && !empty($_POST['title'])){
$total_titles = count($_POST['title']);
for($key = 0; $key < $total_titles; $key++) {
// Clean retrieved client data
$pageName= $_POST['titles'];
}
// Check files
if(isset($_FILES['userfile']['name'])) {
// Count the number of uploaded files
$total_files = count($_FILES['userfile']['name']);
// Loop on uploaded files
for($key = 0; $key < $total_files; $key++) {
// Check if file is selected
if(isset($_FILES['userfile']['name'][$key]) && $_FILES['userfile']['size'][$key] > 0) {
$original_filename = $_FILES['userfile']['name'][$key];
// Get the file extension
$extension = pathinfo($original_filename, PATHINFO_EXTENSION);
// Get filename without extension
$filename_without_extension = basename($original_filename, '.'.$extension);
// Generate new filename
$new_filename = str_replace(' ', '_', $filename_without_extension) . '_' . '.' . $extension;
// Upload the file with new name
move_uploaded_file($_FILES['userfile']['tmp_name'][$key], $target_dir . $new_filename);
}
}
}
}
HTML
<div class="container">
<div class="row justify-content-center">
<!-- Page names -->
<form class="form col-xl-6" action="" id="page_list_section" method="post" enctype="multipart/form-data">
<input type="text" name="title[]" placeholder="Title" >
<input type="file" name="userfile[]" >
<input type="text" name="title[]" placeholder="Title" >
<input type="file" name="userfile[]" >
<input type="submit" name="Submit" value="Upload" >
</form>
</div>
</div>
Here is the match:
for($key = 0; $key < $total_files; $key++) {
$title = $_POST['title'][$key];
$filename = $_FILES['userfile']['name'][$key];
}

How to open a Modal Box on successful processing of a PHP script?

I have 2 files which is upload.php and process.php.
In my upload.php file, I have a form like this:
<form action="upload.php" method="post" enctype="multipart/form-data">
<h5>Upload File</h5>
<p>.jpg and .png only.</p>
<input type="file" name="myfile" required> <br><br>
<h5>Choose action</h5>
<select class="form-control" name="action"required>
<option>No action (Finished)</option>
<option>Please Check</option>
</select><br>
<h5>Who are you</h5>
<select class="form-control" name="uploader" required>
<option>Person A</option>
<option>Person B</option>
<option>Person C</option>
</select><br>
<h5>Remark</h5>
<textarea name="remark" style="resize:none; width:100%; height:100px;">-</textarea><br><br>
<button type="submit" name="save" class="btn btn-dark btn-block">Upload</button><br>
</form>
In my process.php:
if (isset($_POST['save'])) { // if save button on the form is clicked
// name of the uploaded file
$filename = $_FILES['myfile']['name'];
$uploader = $_POST['uploader'];
$action = $_POST['action'];
$remark = $_POST['remark'];
// destination of the file on the server
$destination = 'uploads/' . $filename;
// get the file extension
$extension = pathinfo($filename, PATHINFO_EXTENSION);
// the physical file on a temporary uploads directory on the server
$file = $_FILES['myfile']['tmp_name'];
$size = $_FILES['myfile']['size'];
if (!in_array($extension, ['jpg','png'])) {
echo '<script language="javascript">';
echo 'alert("Upload failed! Your file extension must be .jpg or .png")';
echo '</script>';
} elseif ($_FILES['myfile']['size'] > 1000000) { // file shouldn't be larger than 1Megabyte
echo "File too large!";
} else {
// move the uploaded (temporary) file to the specified destination
if (move_uploaded_file($file, $destination)) {
$sql = "INSERT INTO files (name, size, uploader, action, remark, downloads) VALUES ('$filename', $size, '$uploader', '$action', '$remark', 0)";
if (mysqli_query($conn, $sql)) {
echo '<script language="javascript">';
echo 'alert("File uploaded successfully.")';
echo '</script>';
}
} else {
echo '<script language="javascript">';
echo 'alert("Failed to upload file.")';
echo '</script>';
}
}
}
How do I achieve: if the file upload is successful, a modal box that looks like this will show up to say the upload is success? For now, like you see in the code, I only make it showing an alert.
I think I just solved my own problem.
I add the modal in my upload.php and then I add this javascript so that I can trigger the modal box by direct url.
<script type="text/javascript">
$(document).ready(function() {
if(window.location.href.indexOf('#success') != -1) {
$('#success').modal('show');
}
});
</script>
Then, in process.php, if the upload is success, redirect to mywebsite.com/upload.php#success
header(Location: 'upload.php#success')
If anyone has better solution, feel free to share it. :)

Uploading Multiple Files to Location and Updated Database

I have been working on a multi-image upload function that I can't seem to make work. It currently will only work if I have a single image uploaded. I can't figure out what is going wrong with this script.
This is the function to upload images:
if(isset($_POST["btnSubmit"])){
$errors = array();
$extension = array("jpeg","jpg","png","gif");
$bytes = 1000000;
$allowedKB = 10485760000;
$totalBytes = $allowedKB * $bytes;
$imgDir = "assets/users/".$userLoggedIn."/images/";
if(isset($_FILES["files"])==false)
{
echo "<b>Please, Select the files to upload!!!</b>";
return;
}
foreach($_FILES["files"]["tmp_name"] as $key=>$tmp_name)
{
$uploadThisFile = true;
$file_name=$_FILES["files"]["name"][$key];
$file_tmp=$_FILES["files"]["tmp_name"][$key];
$ext=pathinfo($file_name,PATHINFO_EXTENSION);
if(!in_array(strtolower($ext),$extension))
{
array_push($errors, "File type is invalid. Name:- ".$file_name);
$uploadThisFile = false;
}
if($_FILES["files"]["size"][$key] > $totalBytes){
array_push($errors, "File size is too big. Name:- ".$file_name);
$uploadThisFile = false;
}
if($uploadThisFile){
$filename = basename($file_name,$ext);
$newFileName = uniqid().$filename.$ext;
move_uploaded_file($_FILES["files"]["tmp_name"][$key],$imgDir.$newFileName);
// current date and time
$date_added = date("Y-m-d H:i:s");
$imagePath = $imgDir.$newFileName;
$query = "INSERT INTO images(date_added, added_by, image, deleted) VALUES('$date_added', '$userLoggedIn','$imagePath', 'no')";
mysqli_query($con, $query);
}
}
header("Location: edit-images.php");
$count = count($errors);
if($count != 0){
foreach($errors as $error){
echo $error."<br/>";
}
}
}
?>
I thought the issue might be with size but I cut the condition to prevent it from uploading with no luck. I feel like I might be missing something in the foreach but I am completely stuck. I appreciate your help!
Here is the form I am using to upload:
<form method="post" enctype="multipart/form-data" name="formUploadFile" id="uploadForm" action="edit-images.php">
<div class="form-group">
<label for="exampleInputFile">Select file to upload:</label>
<input type="file" id="exampleInputFile" name="files[]" multiple="multiple">
<p class="help-block"><span class="label label-info">Note:</span> Please, Select the only images (.jpg, .jpeg, .png, .gif)</p>
</div>
<button type="submit" class="btn btn-primary" name="btnSubmit" >Start Upload</button>
</form>

Warning: Invalid argument supplied for foreach() - uploading photos form

Hi I'm new to php and keep getting this error: "Warning: Invalid argument supplied for foreach() in /home/site/folder/upload.php on line 61."
I'm trying to build a form in which users can upload one or more photos automatically to a directory to then be displayed else where.
Whenever I use this form I created it functions properly on my website but unfortunately it keeps printing that error out and would like it to go away. Here is my code I'm working with:
<div>
<form action="upload.php" enctype="multipart/form-data" method="POST">
<input type="file" name="images[]" multiple="multiple"/>
<input type="submit" name="submit" value="upload images"/>
<form/>
<?php
// check if uploads directory exists
$dir = "images/";
if(!is_dir($dir))
{
echo "Directory not found, let's create the folder.";
mkdir($dir,"0777", true);
}
$countimg = 0;
$allimg = 0;
foreach($_FILES["images"]["name"] as $k=>$name)
{
$allimg++;
$imgname = $_FILES["images"]["name"][$k];
$sizeimg = $_FILES["images"]["size"][$k];
$tmpname = $_FILES["images"]["tmp_name"][$k];
//2.
$extension = strtolower(pathinfo($dir.$imgname, PATHINFO_EXTENSION));
if($extension=='png' || $extension=='jpg' ||$extension=='jpeg' ||$extension=='gif')
{
if($sizeimg < 2097152){
if(!file_exists($dir.$imgname)){
//1.
if(move_uploaded_file($tmpname,$dir.$imgname))
{
$countimg++;
}
}
}
}
}
echo "You are trying to upload $allimg images".'<br>';
echo "From $allimg image(s) - $countimg was/were uploaded with success".'<br>';
$z = $allimg - $countimg;
echo "$z image(s) were not uploaded: Not an image, over 2MB, or already uploaded.";
?>
</div>
Try
if (count($_FILES)) {
foreach($_FILES["images"]["name"] as $k=>$name) {
....
}
}
I tested your script, it works fine. The error message appears because you are not checking that a file got uploaded before starting the foreach. If I land on the page, the PHP code will still be triggered. To fix this, you may use the below:
<div>
<form action="upload.php" enctype="multipart/form-data" method="POST">
<input type="file" name="images[]" multiple="multiple"/>
<input type="submit" name="submit" value="upload images"/>
<form/>
<?php
if( $_POST['submit'] ) {
$dir = "images/";
if(!is_dir($dir))
{
echo "Directory not found, let's create the folder.";
mkdir($dir,"0777", true);
}
$countimg = 0;
$allimg = 0;
foreach($_FILES["images"]["name"] as $k=>$name)
{
$allimg++;
$imgname = $_FILES["images"]["name"][$k];
$sizeimg = $_FILES["images"]["size"][$k];
$tmpname = $_FILES["images"]["tmp_name"][$k];
//2.
$extension = strtolower(pathinfo($dir.$imgname, PATHINFO_EXTENSION));
if($extension=='png' || $extension=='jpg' ||$extension=='jpeg' ||$extension=='gif')
{
if($sizeimg < 2097152){
if(!file_exists($dir.$imgname)){
//1.
if(move_uploaded_file($tmpname,$dir.$imgname))
{
$countimg++;
}
}
}
}
}
echo "You are trying to upload $allimg images".'<br>';
echo "From $allimg image(s) - $countimg was/were uploaded with success".'<br>';
$z = $allimg - $countimg;
echo "$z image(s) were not uploaded: Not an image, over 2MB, or already uploaded.";
}
?>
</div>
if( $_POST['submit'] ) will ensure that the form is submitted prior to running the rest of the PHP code.

php - naming Multiple file input fields on a form

I am wanting to have multiple fields on one form that can insert files.
I have the below script, but I want to be able to identify what field the inserted file belongs to in the saved name.
<form action="" method="post" enctype='multipart/form-data' id="form" name="form">
Input 1<input type="file" name="upload[]" >
Input 2<input type="file" name="upload[]" >
Input 3<input type="file" name="upload[]" >
<button id="submit-button">Upload</button>
</form>
<?php
//if(isset($_POST['submit']) && !empty($_POST) ){
$count = 0;
$max_file_size = 5000000;
if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST"){
// Loop $_FILES to exeicute all files
foreach ($_FILES['upload']['name'] as $f => $name) {
$path = 'documents'; //path of directory
if ($_FILES['upload']['error'][$f] == 4) {
continue; // Skip file if any error found
} else {
if ($_FILES['upload']['size'][$f] > $max_file_size) {
$message[] = "$name is too large!.";
continue; // Skip large files
}
else {
// No error found! Move uploaded files
//$name_of_file = $_FILES['username']['name'][$f];
$temp_name = $_FILES['upload']['tmp_name'][$f]; //[$count];
move_uploaded_file($temp_name, "$path/"."$name");
$count++; // Number of successfully uploaded file
}
}
}
}
At the moment it just saves the files into the one location, so I cant differentiate them and identify which field they are from.
can anyone please help?
I have worked it out. I have taken the comments above and placed an Text input field at each of the File Fields. These could also be hidden fields if you need set names.
Then I scroll through them and save the names and apply those names on the server side.
Thanks to the comments, they helped me see the solution.
<form action="" method="post" enctype='multipart/form-data' id="form" name="form">
<input type="text" name="input0" value=""><input type="file" name="upload[]" ><br><br>
<input type="text" name="input1" value=""><input type="file" name="upload[]" ><br><br>
<input type="text" name="input2" value=""><input type="file" name="upload[]" ><br><br>
<button id="submit-button">Upload</button>
</form>
<?php
$count = 0;
$max_file_size = 500000000000;
if(isset($_POST) and $_SERVER['REQUEST_METHOD'] == "POST"){
// Loop $_FILES to exeicute all files
$x = 0;
$input = "input";
while ($x <= 2){
$field_name = $input.$x;
$field[$x] = $_POST[$field_name];
$x++;
}
foreach ($_FILES['upload']['name'] as $f => $name) {
$path = 'documents'; //path of directory
if ($_FILES['upload']['error'][$f] == 4) {
continue; // Skip file if any error found
} else {
if ($_FILES['upload']['size'][$f] > $max_file_size) {
$message[] = "$name is too large!.";
continue; // Skip large files
}
else {
$temp_name = $_FILES['upload']['tmp_name'][$f]; //[$count];
move_uploaded_file($temp_name, "$path/"."$field[$count]"."$name");
$count++; // Number of successfully uploaded file
}
}
}
}

Categories