I am new here, nice to meet you.
I'm trying create a clean copy of a picture uploaded by a user after security checks, and to save this copy in a designated folder and in my DB. I'm working with XAMPP on Windows 10 and I granted the right permissions for the said folder. My code is below:
/*bit of code for picture addition, in a function for album publication*/
if($_FILES['albumCover']['error'] === 0) {
$covType;
$createCover;
$covName = guidv4();
$imgRegex = '/^[a-z\d][^.]*\.(jpe?g$)|\.(png$)/i';
$covInfo = finfo_open(FILEINFO_MIME_TYPE);
$covMime = finfo_file($covInfo, $_FILES['albumCover']['tmp_name']);
finfo_close($covInfo);
if(!preg_match($imgRegex, $_FILES['albumCover']['name']) ||
str_contains($_FILES['albumCover']['name'], ' ') ||
in_array($_FILES['albumCover']['type'], ['image/jpeg','image/png'])||
strpos($covMime, 'image/') !== 0)
{
$addMessages['errors'][] = 'Caractère autorisé pour le nom d\'image : lettres sans
accent / sans trémas / sans cédille, chiffres, tirets et underscores. Fichiers
autorisés : images .jpg, .jpeg ou .png.';
}
if(empty($addMessages['errors'])) {
if(preg_match($imgRegex, $_FILES['albumCover']['name'])
&& $_FILES['albumCover']['type'] == 'image/jpeg'
&& strpos($covMime, 'image/') !== 0)
{
$covType = 'jpeg';
$createCover = imagecreatefromjpeg($_FILES['albumCover']['tmp_name']);
imagejpeg($createCover,
self::COV_SECURE_PATH.$covName.'.'.pathinfo($_FILES['albumCover']['name'],
PATHINFO_EXTENSION)
);
move_uploaded_file($_FILES['albumCover']['tmp_name'],
self::COV_SECURE_PATH.'/'.$_FILES['albumCover']['name']);
} elseif(preg_match($imgRegex, $_FILES['albumCover']['name'])
&& $_FILES['albumCover']['type'] == 'image/png'
&& strpos($covMime, 'image/') !== 0)
{
$covType = 'png';
$createCover = imagecreatefrompng($_FILES['albumCover']['tmp_name']);
imagepng($createCover,
self::COV_SECURE_PATH.$covName.'.'.pathinfo($_FILES['albumCover']['name'],
PATHINFO_EXTENSION));
move_uploaded_file($_FILES['albumCover']['tmp_name'],
self::COV_SECURE_PATH.'/'.$_FILES['albumCover']['name']);
}
}
}
A few more details: the bit of code above is part of a class method. The constant COV_SECURE_PATH is declared in the class, before the method. And the guidv4() function for the picture name is in the same file, before the declaration of the class.
I have no PHP error messages, my prints display the right name and extension of each file and I declared the attribute enctype="multipart/form-data" in my HTML form. The pictures are saved in my DB (I will add the code regarding the DB if needed), but they won't be saved in my folder and I don't know what I'm missing. So far I haven't found an answer when searching in any site, any help will be very appreciated.
Well, I have finally fixed everything. My error was: if(preg_match($imgRegex, $_FILES['albumCover']['name']) && $_FILES['albumCover']['type'] == 'image/jpeg' && strpos($covMime, 'image/') !== 0) {
instead of if(preg_match($imgRegex, $_FILES['albumCover']['name']) && $_FILES['albumCover']['type'] == 'image/jpeg' && strpos($covMime, 'image/') === 0) {
And I also realised that I hadn't activated GD in my php.ini, now it's done.
Thanks to everyone who answered me!
take a look at my image validation...
//connecting to the database
$mysqli = mysqli_connect( 'localhost', 'root', '', 'img_validation' )
or
die( 'Database connection error => '.mysqli_connect_error() );
//errors and success message handling
$errors = array();
$success = array();
//imgs dir
$imgs_dir = './assets/imgs/';
//if upload button is pressed...
if ( isset( $_POST['upload'] ) ) {
//get image info...
$imgName = $_FILES['image']['name'];
$imgTmp = $_FILES['image']['tmp_name'];
$imgSize = $_FILES['image']['size'];
//image validation
if ( $imgName ) {
//get extension info
$imgExt = strtolower( pathinfo( $imgName, PATHINFO_EXTENSION ) );
//allowed image extensions
$allowExt = array( 'jpg', 'jpeg', 'png' );
//create new random image name
$uploadedPic = 'user-upload-'.rand( 100000, 999999 ).'.'.$imgExt;
//validate image extension
if ( in_array( $imgExt, $allowExt ) ) {
//max image upload size 3MB
if ( $imgSize < 3000000 ) {
//move image file to designated directory/folder
move_uploaded_file( $imgTmp, $imgs_dir.$uploadedPic );
} else {
array_push( $errors, "Image too large. Max. upload size 3MB." );
}
} else {
array_push( $errors, "<script type='text/javascript'>
alert('JPG, JPEG and PNG formats required.\\nMax. upload size 3MB.');</script>" );
array_push( $errors, "Please select a valid image." );
}
} else {
$uploadedPic;
}
//if found no errors...
if ( count( $errors ) == 0 ) {
//insert new record in `user_uploads` table in the database...
$admin = mysqli_query( $mysqli, "INSERT INTO user_uploads (image) VALUES ('$uploadedPic');" );
if ( $admin == 1 ) {
//success message
array_push( $success, "Image uploaded successfully." );
//redirect to profile after 2 seconds...
header( 'refresh: 2; url=http://localhost/img-validation/' );
} else {
array_push( $errors, mysqli_error() );
}
}
}
When I was at the early learning stage of PHP, I write this code and hope this will work for you : )
Related
I was trying to write a PHP code that uploads all images to mysql db and shows the images metadata in columns. in my code it uploads the images but does not show the metadata. for example I tried to insert the width of the image, I made a column for that and when I upload the image the width is always 0. can someone check my code and help me find a solution for than?
<?php
// Include the database configuration file
include_once 'dbconfig.php';
if(isset($_POST['submit'])){
// File upload configuration
$targetDir = "C:\\xampp\\htdocs\\uploaded\\";
$allowTypes = array('jpg','png','jpeg','gif');
$statusMsg = $errorMsg = $insertValuesSQL = $errorUpload = $errorUploadType = '';
$fileNames = array_filter($_FILES['files']['name']);
if(!empty($fileNames)){
function getExif( $filename, $key1, $key2) {
$width = 0;
$allowedFiletypes = array("jpg","jpeg","tif","tiff");
if(in_array(strtolower(substr($filename, -3)),$allowedFiletypes)) {
if(exif_read_data($filename) == true) {
$exif = exif_read_data($filename, 0, true);
foreach ($exif as $key => $section) {
foreach ($section as $name => $val) {
if($key === $key1 AND $name === $key2){
$width = $val;
}
}
}
}
return $width;
} else {
print "filetype not supported";
}
}
$key1 = "IFD0";
$key2 = "ImageWidth";
foreach($_FILES['files']['name'] as $key=>$val){
// File upload path
$fileName = basename($_FILES['files']['name'][$key]);
$width = getExif( $fileName, $key1, $key2);
$targetFilePath = $targetDir . $fileName;
// Check whether file type is valid
$fileType = pathinfo($targetFilePath, PATHINFO_EXTENSION);
if(in_array($fileType, $allowTypes)){
// Upload file to server
if(move_uploaded_file($_FILES["files"]["tmp_name"][$key], $targetFilePath)){
// Image db insert sql
$insertValuesSQL .= "('".$fileName."', NOW(), '".$width."'),";
}else{
$errorUpload .= $_FILES['files']['name'][$key].' | ';
}
}else{
$errorUploadType .= $_FILES['files']['name'][$key].' | ';
}
}
// Error message
$errorUpload = !empty($errorUpload)?'Upload Error: '.trim($errorUpload, ' | '):'';
$errorUploadType = !empty($errorUploadType)?'File Type Error: '.trim($errorUploadType, ' | '):'';
$errorMsg = !empty($errorUpload)?'<br/>'.$errorUpload.'<br/>'.$errorUploadType:'<br/>'.$errorUploadType;
if(!empty($insertValuesSQL)){
$insertValuesSQL = trim($insertValuesSQL, ',');
// Insert image file name into database
$insert = $db->query("INSERT INTO images(file_name, uploaded_on, image_width) VALUES $insertValuesSQL");
if($insert){
$statusMsg = "Files are uploaded successfully.".$errorMsg;
}else{
$statusMsg = "Sorry, there was an error uploading your file.";
}
}else{
$statusMsg = "Upload failed! ".$errorMsg;
}
}else{
$statusMsg = 'Please select a file to upload.';
}
}
?>
<form action="upload1.php" method="post" enctype="multipart/form-data">
Select Image Files to Upload:
<input type="file" name="files[]" multiple >
<input type="submit" name="submit" value="UPLOAD">
</form>
my goal is to upload images with all their metadata
You are incorrectly passing in the filename rather than the file itself - and a name does not have any EXIF data attributes. One other issue that you will encounter with EXIF perhaps is that not every camera adds the same details so there ar eno guarantees that a particular property will exist within a particular section so forking the processing logic around that is needed.
You can simplify the getExif function using array_key_exists rather than the nested loops which can be prone to issues. For example, a bare-bones piece of PHP without the SQL portion.
The getExif below either returns exactly the item requested or the entire exif response which can be used to fork the logic as mentioned. In testing I found just one image that contained both the section and required parameter ($key1,$key2- renamed for clarity)
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
Select Image Files to Upload:
<input type="file" name="files[]" multiple />
<input type="submit" />
</form>
<?php
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );
function uploaderror( $error ){
switch( $error ) {
case UPLOAD_ERR_INI_SIZE: return "The uploaded file exceeds the upload_max_filesize directive in php.ini";
case UPLOAD_ERR_FORM_SIZE: return "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form";
case UPLOAD_ERR_PARTIAL: return "The uploaded file was only partially uploaded";
case UPLOAD_ERR_NO_FILE: return "No file was uploaded";
case UPLOAD_ERR_NO_TMP_DIR: return "Missing a temporary folder";
case UPLOAD_ERR_CANT_WRITE: return "Failed to write file to disk";
case UPLOAD_ERR_EXTENSION: return "File upload stopped by extension";
default: return "Unknown upload error";
}
}
function getExif( $filename, $section=false, $param=false ) {
if( $section & $param ){
$exif = #exif_read_data( $filename,0, true );
if( array_key_exists( $section, $exif ) && array_key_exists( $param, $exif[ $section ] ) )return $exif[ $section ][ $param ];
return $exif;
}
return false;
}
if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_FILES['files'] ) ){
$exts = array('jpg','jpeg','tif','tiff');
$files=(object)$_FILES['files'];
foreach( $files->name as $i => $void ){
$name = $files->name[$i];
$size = $files->size[$i];
$type = $files->type[$i];
$tmp = $files->tmp_name[$i];
$error= $files->error[$i];
$errors=array();
if( !$error == UPLOAD_ERR_OK )$errors[]=uploaderror( $error );
if( empty( $errors )){
$ext = strtolower( pathinfo( $name, PATHINFO_EXTENSION ) );
$targetDir = __DIR__ . '/uploads';
$targetFile = sprintf('%s/%s',$targetDir,$name);
if( in_array( $ext, $exts )){
/*
What you wish to find in the exif...
*/
$section = "IFD0";
$param = "ImageWidth";
/*
find and process...
*/
$result = getExif( $tmp, $section, $param );
if( !is_numeric( $result ) or is_array( $result ) ){
$errors[]=sprintf('Unable to locate property "%s" within designated section: "%s"',$param,$section);
$errors[]=$result;
}else{
# just to show the data...
printf('<pre>%s</pre>',print_r( $result, true ) );
/*
save file to disk...
*/
$status=move_uploaded_file( $tmp, $targetFile );
if( !$status )$errors[]='Failed to save file';
/*
sql... use a Prepared Statement!
*/
$sql='insert into images( `file_name`, `uploaded_on`, `image_width` ) values (?,?,?)';
/*
$stmt=$db->prepare($sql);
$args=array(
$name,
date('Y-m-d H:i:s'),
$result
);
$stmt->bind_param('sss',...$args);
$stmt->execute();
*/
}
}else{
$errors[]='unknown file extension: '.$ext;
}
}
if( !empty( $errors ) )printf('<pre>%s</pre>',print_r($errors,true));
}
}
?>
</body>
</html>
Can someone help me add a PHP IF command for multi file upload fields so that I can add a header text if user uploaded files? I have 10 multi file upload fields that I am using as part of Gravity Forms. I am outputting this to a pdf and just cant figure this out.
Here is my code that posts the images to the pdf.
if ( is_array( $form_data['field']['170_path'] ) ) {
$allowed_extensions = array( 'jpg', 'jpeg', 'png', 'gif' );
/* Not sure how to write the if command */
/* I tried the code below but it doesnt work*/
if(empty( $form_data['field']['170_path'] ) && empty( $path ) ) {
echo "there is no file uploaded";
exit;
} else {
echo "there is file";
}
/* --------------------- */
/* The code below is working. I just need help with the section above */
foreach ( $form_data['field']['170_path'] as $path ) {
$extension = strtolower( pathinfo( $path, PATHINFO_EXTENSION ) );
if( in_array( $extension, $allowed_extensions ) && is_file( $path ) ) {
echo '<img src="'. $path .'" />';
}
}
}
The code below is uploading and displaying files on the upload.php page and it's working fine. The problem I have is that it's not displaying the files if I copy and paste the url of the upload.php page into a new webpage.
upload.php code
<?php
if (isset($_FILES['file_upload'])) {
$file = $_FILES['file_upload'];
$name = $file['name'];
$type = $file['type'];
$tmp_location = $file['tmp_name'];
$upload = 'uploads';
$final_destination = $upload.'/'.$name;
$error = $file['error'];
$max_upload_size = 2097152;
$size = $file['size'];
$allowedImageTypes = array( 'image/png', 'image/jpeg', 'image/gif', );
function imageTypeAllowed($imageType){
global $allowedImageTypes;
if(in_array($imageType, $allowedImageTypes)){
return true;
}
else{
return false;
}
}
//Check for errors
if($error > 0 || is_array($error)){
die("Sorry an error occured");
}
//Check if file is image
//Only required if image is only whjat we need
if(!getimagesize($tmp_location)){
die("Sorry, you can only upload image types");
}
if(!imageTypeAllowed($type)){
die("Sorry, file type is not allowed");
}
if(file_exists($final_destination)){
$final_destination = $upload.'/'.time().$name;
}
if(!move_uploaded_file($tmp_location, $final_destination)){
die("Cannot finish upload, something went wrong");
}
$handle = opendir('uploads');
if($handle){
while(($entry = readdir($handle)) !== false){
if($entry != '.' && $entry != '..'){
echo "$entry<br>";
}
}
closedir($handle);
}
}
?>
<h2>File Successfully uploaded!</h2>
If you indent your code to be human-readable, you'll find that the entire server-side code block is wrapped in this conditional:
if (isset($_FILES['file_upload'])) {
// all of your code
}
This means that all of that server-side code will execute only if a file_upload value is POSTed to the form. When you copy/paste the URL into a new browser window and invoke that request, you're invoking a GET request with no form values. Since you're not uploading a file in this request, the isset() condition evaluates to false and your code isn't executed.
You should separate your functionality into two groups:
Handling the upload.
Displaying the current state of the data.
The code for handling the upload should execute only when an upload is present. The code for displaying the data should execute always.
If I'm reading your code correctly, all you should need to do is split out the last few parts:
if (isset($_FILES['file_upload'])) {
// the rest of your code
}
$handle = opendir('uploads');
if($handle){
while(($entry = readdir($handle)) !== false){
if($entry != '.' && $entry != '..'){
echo "$entry<br>";
}
}
closedir($handle);
}
I've been making an image uploader and I'm having a couple of issues.
Code is so simple: it gets a file (zip file) froom a form and a couple of info text, then generates an url if it isn't exists previously and then extracts the file there.
First one is, that the form variables ($_post["serie"] and $_POST["capitulo"] seems to expire if the file is large and take some time to upload.
Second one is that it tends to fail when uploading not jpg stuff >< and don't know why.
Thanks for your efforts in advance.
<?php
require_once('pclzip.lib.php');
function preextract($p_event, &$p_header) {
$info = pathinfo($p_header['filename']);
if ($info['extension'] == 'gif' || $info['extension'] == 'jpg' || $info['extension'] == 'png' || $info['extension'] == 'jpeg') {
return 1;
} else {
return 0;
}
}
if(is_uploaded_file($_FILES['file']['tmp_name'])) {
echo $_FILES['file']['tmp_name'];
}
$archive = new PclZip($_FILES['file']['tmp_name']);
$extractpath = "../series/" . $_POST["serie"] . "/" . $_POST["capitulo"];
echo $extractpath;
if (file_exists($extractpath)) {
} else {
mkdir($extractpath, 0755);
}
if (($archive->extract(PCLZIP_OPT_PATH, $extractpath, PCLZIP_CB_PRE_EXTRACT, 'preextract') == 0)) {
echo "\n error in extraction";
} else {
echo "\n done";
}
?>
A few things...
You need to increase the max filesize to submit larger files:
ini_set( 'upload_max_filesize', '100M' );
ini_set( 'post_max_size', '100M' );
Change your file_exists check:
if ( !file_exists( $extractpath ) )
mkdir( $extractpath, 0755 );
Change your extension check:
return in_array( $info['extension'], array( 'png', 'jpg', 'jpeg', 'gif' ) ) ? 1 : 0;
I'm not sure why it only works on one extension, maybe PclZip has a setting prohibiting certain files, so look for that.
For some reason when trying to upload a zip file this function always returns false. The directories are all set to 0777 for permissions. I'm stumped as to what could be wrong.
function uploadProof ( $file, $email )
{
// Check or create for existing directory
if ( !is_dir('client_files/'.$email))
{
mkdir('client_files/'.$email);
if ( !is_dir('client_files/'.$email.'/proof/'))
{
mkdir('client_files/'.$email.'/proof/');
}
}
// Target path
$target_path = 'client_files/'.$email.'/proof/';
// File information
$filename = date('Y_M_D').$email.'.zip';
$tmp_name = $file['tmp_name'];
$filesize = $file['size'];
// Blacklist and Max file info
$max_allowed = (1024 * 1024) * 99; // 99 MB
$blacklist = array(
'.pl', '.php', '.phtml', '.php3', '.php4', '.php5'
);
// Check filename
foreach ( $blacklist as $nope)
{
if ( preg_match("/$nope\$/i", $filename))
{
die("As previously stated, we do not allow php files of any type\n
to be uploaded to our server.\n\n");
}
}
// Check filesize
if ( $filesize > $max_allowed)
{
die("File is too big, file needs to be less than <em>20MB</em> in size.");
}
else
{
$target = $target_path.$filename;
if (move_uploaded_file($tmp_name, $target))
{
return true;
}
else
{
return false;
}
}
}
You do need to check if the upload actually succeeded, before going on to do what might be a totally useless set of operations:
function uploadProof ( $file, $email ) {
if ($file['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $file['error']);
}
...
}
The error codes are defined here.