Multiple upload files with PHP and MySQL, save data and showing them

Hi,

I have SQL table like this:
id | name | surname | dateofbirth | address | contact | dateofentrie | attachement1 | attachement2 | otherattachements

So I need in one form to add 2 files in 2 fields with input type="file", and one field is for upload multiple files.

<?php
require ('functions.php');

if (isset($_POST['submit'])){
	$name=$_POST['name'];
	$surname=$_POST['surname'];
	$dateofbirth=$_POST['dateofbirth'];
	$address=$_POST['address'];
	$contact=$_POST['contact'];
	$dateofentrie=$_POST['dateofentrie'];
        $attachement1=$_FILES['attachement1'];
	  $url = uploadAttachement1($attachement1);
        $attachement2=$_FILES['attachement2'];
	  $url2 = uploadAttachement2($attachement2);

$adduser=addNewUser($name,$surname,$dateofbirth,$address,$contact,$dateofentrie,$attachement1,$attachement2,$otherattachements);
	if ($addNewUser) {
		header ('Location: users_list.php');
	}
	else {
		echo "Error";
	}
	}
?>

<p><b>Name:</b> 
<input type="text" class="form-control" name="name"></p>
<p><b>Surname:</b> 
<input type="text" class="form-control" name="surname"></p>
<p><b>Date of birth:</b> 
<input type="date" class="form-control" name="dateofbirth"></p>
<p><b>Address:</b> 
<input type="text" class="form-control" name="address"></p>
<p><b>Contact:</b> 
<input type="text" class="form-control" name="contact"></p>
<p><b>Date of entrie:</b> 
<input type="text" class="form-control" name="dateofentrie" value="<?php echo date('d.m.Y'); ?>" readonly></p>
<p><b>Attachement1 (example: CV):</b> 
<input type="file" class="form-control" name="attachement1"></p>
<p><b>Attachement2 (example: References):</b> 
<input type="file" class="form-control" name="attachement2"></p>
<p><b>Other attachements:(example: certificates etc...)</b>
<input type="file" multiple class="form-control" name="otherattachements" ></p>

Open in new window


Maybe is good to automatic rename files, for example, attachement1: name_surname_cv_dateofentrie.pdf

or if is possible to automatically make new directory if not exist which is named from inputs in fields "name" and "surname".

So I have list of users, and every user is clickable, when click on name, opening user details. In user details I need to show all informations from columns in SQL table and I need to show: example: CV - name_surname_cv_dateofentrie.pdf which is clickable and opening that file. And where is Other attachements I need to show list of files, all files need to be clickable.

I know how to make that for no multiple files, but didnt sure about rename, and moving and creating directories. I am searching for example like this on net, and tutorial, but no successfull.

I have file with functions named: functions.php

function uploadAttachement1($attachement1) {
	if($attachement1){
		$upload=move_uploaded_file($attachement1['tmp_name'],'documents/'.$attachement1['name']);
		if($upload) {
			return "documents/".$attachement1['name'];
		}
		else {
			return null;
		}
	}
}

function uploadAttachement2($attachement2) {
	if($attachement2){
		$upload=move_uploaded_file($attachement2['tmp_name'],'documents/'.$attachement2['name']);
		if($upload) {
			return "documents/".$attachement2['name'];
		}
		else {
			return null;
		}
	}
}

Open in new window



Thank you
Žan AnđićAsked:
Who is Participating?
 
Julian HansenConnect With a Mentor Commented:
The following function returns an array of paths that were used in the
function uploadFajlova ($dokumenti){
  // ARRAY TO STORE RETURNED FILES
  $files = array();
   $dokumenti = $_FILES['files']['name'];
   if (!empty($dokumenti)) {
     for($up=0;$up<count($dokumenti);$up++) {

       // CREATE targetpath FOR FILE
       $targetpath = 'dokumenti/ostali/'.$_FILES['files']['name'][$up];

       // ATTEMPT TO MOVE THE FILE
       if (move_uploaded_file($_FILES['files']['tmp_name'][$up], $targetpath)) {
         // IF SUCCESSFUL THEN ADD TO RETURN ARRAY
         $files[] = $targetpath;
       }
     }
   }

   // RETURN ARRAY OF PATHS TO SUCCESSFUL FILE UPLOADS
   return $files;
 }

Open in new window


The return from the above can be encoded and saved to your DB field for instance

$result = uploadFajlova();
$dbfield = json_encode($result);
// Save $dbfield to your otherfiels DB column

Open in new window

1
 
Julian HansenCommented:
Maybe is good to automatic rename files, for example, attachement1: name_surname_cv_dateofentrie.pdf
Definitely, otherwise you run the risk of collisions - two users uploading using the same filename.
or if is possible to automatically make new directory if not exist which is named from inputs in fields "name" and "surname".
And if you have two users with the same name and surname - again you have a collision.

What I would do is rename the file using an ID / GUID / random name or similar. Store this in the database. At the same time also store the original filename - the one that was used by user when they uploaded. I would also keep the files in a flat space.

If you need to download the file you get the id from the database and in the download code you create (using headers) the filename you want it to download as again using the original name you saved in the database.

This option allows you the most flexibility.

Now to the other files. This points to a potentially bad DB design. A better option might be to rationalise your DB and create a files table that you then populate with files linked to the parent user on the user id. This will require a JOIN to retrieve the data but it will mean you can handle as many files per user as required.

If you want / have to store in a single record then I would consider creating an array of objects that store the file details and then JSON encode (or serialize - I prefer JSON) and store the JSON string in the other attachments field.

When you display the user record you simply json_decode() the string and use the decoded data to render the file list.
0
 
Žan AnđićAuthor Commented:
Thank you for answer,

For make new directories I can maybe add column n DB identification number from personal card (jmbg) and when making directory use $name,$surname and $jmbg
I can make new table in DB, named files, and make columns. What is the best way? how to table where is files with user details?
How to do that with JSON?
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Julian HansenCommented:
You can use a unique user id to create a directory if you wish.

To create a separate table for your files I would do this
create table `attachments`( 
   `id` int NOT NULL AUTO_INCREMENT , 
   `date` timestamp DEFAULT CURRENT_TIMESTAMP , 
   `usreid` int , 
   `path` varchar(255) , 
   `original_filename` varchar(255) , 
   PRIMARY KEY (`id`)
 )

Open in new window

(the timestamp is optional - I added it in case upload date is important)
For each attachment you would add a record to this table linked on userid
Path is the name of the file (with directory) on disk
Original filename is the name the user used when they uploaded the file.

You would then retrieve your data like so

SELECT * FROM userTable u LEFT JOIN attachments a ON u.id = a.userid

Open in new window


The first record gives you your standard user data which you use to populate the profile as well as the first attachment. You then iterate over the remaining records to get the rest of the attachments.
// Assume $userid holds id of user you want to view
$query = "SELECT * FROM userTable u LEFT JOIN attachments a ON u.id = a.userid WHERE u.id = '{$userid}'";
$result = $mysqli->query($query);
if (!$result) {
  // handle error here
}
// Get first record for user data and first attachment
$row = $result->fetch_object();
// Populate user data here and first attachment
while ($row = $result->fetch_object()) {
   // complete rest of attachment list here
}

Open in new window

0
 
Žan AnđićAuthor Commented:
Thank you

What is solution without creating table in database for files?

After uploading show array with filenames? How ?
0
 
Julian HansenCommented:
First of all change the name on your <input> to an array like this
<input type="file" multiple class="form-control" name="otherattachements[]" >

Open in new window

You could then use something like this to generate a string containing the data for the additional attachments
$otherattachment = isset($_FILES['otherattachements']) ? $_FILES['otherattachements'] : array('name' => array());
$attachments_array= array();
foreach($otherattachment['name'] as $key => $attachment) {
   $attachment = new stdClass;
   $attachment->name = $attachment;
   $savepath = getUserSavePath($userid);
   // Save the file to the right location
   move_uploaded_file($otherattachment['tmp_name'][$key], $savepath);
   $attachment->path = $savepath;
   $attachments_array[] = $attachment;
}

$dbattachments= json_encode($attachments_array);
// Add $dbattachments to your query and save in the database

function getUserSavePath($userid) {
   // Implement your unique path creation here
}

Open in new window

0
 
Žan AnđićAuthor Commented:
Does that can all be in one function named: uploadFiles

so
function uploadFiles ($otherattachment){
$otherattachment = isset($_FILES['otherattachements']) ? $_FILES['otherattachements'] : array('name' => array());
$attachments_array= array();
foreach($otherattachment['name'] as $key => $attachment) {
   $attachment = new stdClass;
   $attachment->name = $attachment;
   $savepath = getUserSavePath($userid);
   // Save the file to the right location
   move_uploaded_file($otherattachment['tmp_name'][$key], $savepath);
   $attachment->path = $savepath;
   $attachments_array[] = $attachment;
} 
$dbattachments= json_encode($attachments_array);
if ($dbattachements) {
return "mypath/".$dbattachements; 
}
else {
return null; 
}
}

Open in new window

0
 
Julian HansenCommented:
You can put it wherever you want. The code is sample code only you need to adapt it to your situation.
0
 
Žan AnđićAuthor Commented:
Tryed, upload just one file :(
0
 
Julian HansenCommented:
You are going to have to give me more than that.
0
 
Žan AnđićAuthor Commented:
I am attached to you my index.php file, and functions.php file where is function.

in index.php file on line 388 is input field and on lines 97 is final function for add entry in database, and on lines 93 and 92 are variables for documents upload (multiple).

In functions file

on the end you can see.
index.php
funkcije.php
0
 
Julian HansenCommented:
That function worked for me - uploaded 3 files and all were copied to the target folder.

Your code could be structured a bit better.

1. I would move the form processing into its own PHP file. This file loads the form with a require statement
2. Format your code so that it is neater - it is very difficult to debug code that is all over the place
3. This call
$dodajunosbaza=dodajUnosBaza($ime,

Open in new window

Is very messy - consider using an object or an array to pass your variables rather than an overlong parameter list.

If you want help on this you are going to have to provide more information.

Do you get any errors.
What happens when you run the code - what do you expect what are your getting.
0
 
Žan AnđićAuthor Commented:
When I run code - uploaded success, and I get echo information: filename.txt is uploaded, filename2.txt is upladed... Now I want to get filenames and insert into variable which is: putanja_files=unosFajl ...

putanja_files is under dodajunosbaza=dodajUnosBaza($ime,$prezime$.......$putanja_files)


In above variables you can see putanja_rjesenje and putanja_anamneza, and when I click submit button, I in database write filename with full path, from return in function uploadRjesenje and uploadAnamneze. I want the same thing with uploadFajl and putanja_files.
0
 
Julian HansenCommented:
What I am hearing is you want to return the filenames from the function that saves them?

Create an array - store the paths in the array and return the array.

I am not 100% clear on what you are asking so I can't be specific on how to do this.
0
 
Žan AnđićAuthor Commented:
Yes that is what I want,

how to create that array? how that needs to look like?
0
 
Žan AnđićAuthor Commented:
Yes, that works, thank youuu so much

I get text in my sql field:

["dokumenti/ostali/fluid.txt","dokumenti/ostali/home_page.txt","dokumenti/ostali/kategorija korisnika.txt","dokumenti/ostali/korisnik.png"]

Open in new window


Is there way to show that without brackets and quotes and commas, something like this:

dokumenti/ostali/fluid.txt
dokumenti/ostali/home_page.txt
dokumenti/ostali/kategorijakorisnika.txt
dokumenti/ostali/korisnik.png

To put <br> and make links to paths?

And one question more, is there way to use mkdir from variables $name, $surname, $number (number - unique number in database for every user from personal card). I am trying something before, but I have trouble with special characters, if name and surname have čšćžđ, file name be like example:

This is how need to be: Žan_Anđić_178000.doc
I get like this: %$'/an_An%/*-%i/%'_17800.doc

Something with utf8 encode?
0
 
Julian HansenCommented:
You can but that defeats the purpose. You want to be able to access those documents - you are storing multiple document paths in a single list.

I used json_encode so that you can get the array back again when you need those paths
$paths = json_decode($row['extra_files_column_name_here']);
// Now paths is an array of paths.

Open in new window


If you do it the other way you will have to still explode (or similar) the data to get the paths back.

JSON is the easiest way of doing this.
0
 
Žan AnđićAuthor Commented:
You want to be able to access those documents - you are storing multiple document paths in a single list.

Yes that is what I need. Exactly.  

I will try to do that, now.
0
 
Žan AnđićAuthor Commented:
    // IF SUCCESSFUL THEN ADD TO RETURN ARRAY
         $files[] = '<a href="'.$targetpath.'">'.$targetpath.'</a><br>';
       }
     }
   }

   // RETURN ARRAY OF PATHS TO SUCCESSFUL FILE UPLOADS
   return implode(' ',$files);
 }

Open in new window


I am try this, and get all what I want, but with quotes on begin and on the end.

"<a href=dokumenti/ostali/korisnik.png>dokumenti/ostali/korisnik.png</a><br> <a href=dokumenti/ostali/peel_stick2.png>dokumenti/ostali/peel_stick2.png</a><br>"

Open in new window


Need to remove (")
0
 
Julian HansenCommented:
Let me explain why I would not do it this way.

When you store the actual format of the link in the database it locks you into that format. If you decide to change the format in the future - even by 1 character you have to change every record in your database - not good practice.

I also would stay with JSON over implode as it is a standard - it is the same amount of effort to use as explode / implode (if not less) and it is a widely supported and understood format.

As to the issue of the quotes - I don't know what quotes you are referring to nor where you get your data from - the implode should not be causing this - whatever it is - it is not in the code you have shown.
"<a href=dokumenti/ostali/korisnik.png>dokumenti/ostali/korisnik.png</a><br> <a href=dokumenti/ostali/peel_stick2.png>dokumenti/ostali/peel_stick2.png</a><br>"
Are you referring to the double quotes around the above? If so - how are you outputting that string - I need to see all the code from the time you get it from the DB until you output it - what you have given me is simply not enough.
0
 
Žan AnđićAuthor Commented:
Thank you

I fix, put
$putanja_files=str_replace('"','',$red['prilog_ostali']);

Open in new window

Now showing good. This way is not useful if I need to change something in files, or upload more, or something, but when you adding new user in database, and upload files, once when uploaded no changes.

How to this files put in new directory if not exist, directory can be named just from $jmbg (id number), no need for name and surname?
0
 
Julian HansenCommented:
This way is not useful if I need to change something in files, or upload more, or something
Which is why I would use JSON

Add to files
1. Get record from database
2. Get field from record - $row['otherattachements ']
3. Decode
$files = json_decode($row['otherattachements ']);
4. Add new file
$files[] = "Path/To/New/File.txt";
5. Encode
$otherattachments = json_encode($files);
6. Put back in the database
UPDATE [TABLENAME] SET otherattachments='{$otherattachments}' WHERE [FILTER TO FIND RECORD]

Open in new window


How to this files put in new directory if not exist, directory can be named just from $jmbg (id number), no need for name and surname?
I am not sure I understand - are you asking
1. How to make a directory
2. Find a name for a directory
3. How to save the files to a specified directory?
0
 
Žan AnđićAuthor Commented:
I need to save file in directory which will be created for everyuser with mkdir from variable $jmbg and after save get path like on this what we success finished. Just need to save files in new directory
0
 
Julian HansenConnect With a Mentor Commented:
Then I don't understand the problem - just add the directory name to the path.

If you need to create the folder first then just do this
[UNTESTED CODE - PROVIDED FOR ILLUSTRATION ONLY]
$userfolder = "/path/to/save/location/" . $user_specific_path;
if (!is_dir($userfolder)) {
    mkdir($userfolder);
}
foreach($_FILES['tmp_name'] as $up) {
   $targetpath = $userfolder . "/" . $_FILES['name'][$up] 
   if (is_uploaded_file($_FILES['tmp_name'][$up])) {
     move_uploaded_file($_FILES['tmp_name'][$up], $targetpath);
   }
   $files[] = $targetpath;
}

Open in new window

0
 
Žan AnđićAuthor Commented:
Works perfectly.

Thank you Julian.
Now I have just little trouble with special characters when uploading file, making directory and new file name.

I need to replace ćčšđž characters with: ccsdz

I try with str_replace but not successful

EDIT
Successfull
I put this and now works all well
$characters= array("ć", "č", "š", "ž", "đ", "Ć", "Č", "Š", "Ž", "Đ");
	$replacechar= array("c", "c", "s", "z", "d", "C", "C", "S", "Z", "D");
	$name=str_replace($characters,$replacechar,$name);

Open in new window

0
 
Žan AnđićAuthor Commented:
Thank you Julian Hansen for your time and help :)
0
 
Julian HansenCommented:
You are welcome.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.