What are best practices for uploading files using PHP to ensure that a database is also updated?
Current approach
1) Form validation confirms all fields are of valid types, lengths and clean of xss attacks.
2) File uploaded to server with user submitted filename
3) Database updated with user submitted details including filename
Is that a safe way? Would it be better to update the database first, then query the database for the filename and then upload the file using the database-retrieved filename?
Not looking for code necessarily but rather the philosophy. Thanks!
I would use this order:
I strongly suggest using some PDO
-like library to "talk" to database as these throw exceptions, instead of raising errors (like mysql_**
function). That way you will know for sure if your query succeeded without constantly checking result of database functions...
Form validation is an essential part of any web application so it's good to see that on the list. You're combining two of the most risky elements of web applications here, file uploads and database interaction so you obviously need to tread carefully. I guess that's why you're asking!
My suggestion in terms of approach is firstly not to use user submitted filenames, that opens up a whole area of risk you don't need. Unless this is a required feature of your app, generate a new random filename in PHP and use move_uploaded_file to copy from the PHP assigned tmp_name to your new random filename.
Once you've performed this move you can update the database with the location of the file.
My approach would therefore be:
I know you weren't after code but here are a couple of little snippets from a working file upload I have, it doesn't do the database part but that would be straightforward to add.
function generate_filename() {
// could be improved upon really
$random_string = random_string(8);
$filename = $random_string . time() . ".jpg";
return $filename;
}
if ($_FILES["file_upload"]["size"] != 0) {
$file_name = generate_filename();
$file_path = "/" . $upload_directory . "/" . $file_name;
$target_file_name = SITE_ROOT . $file_path; // SITE_ROOT is a constant for the file system location. This could be /var/www/images for example.
if ($_FILES["file_upload"]["type"] == "image/jpeg") {
if (getimagesize($_FILES["file_upload"]["tmp_name"])) {
if (move_uploaded_file($_FILES["file_upload"]["tmp_name"],$target_file_name)) {
exit_status("File uploaded successfully to $file_path");
} else {
exit_status("Eek, something went wrong with your image upload");
}
} else {
exit_status("Not a valid image");
}
} else {
exit_status("Invalid file type. We only support JPEG");
}
} else {
exit_status("You didn’t specify a file to upload. Try again");
}