I have a PHP script that, if a user-uploaded image file isn't a .png image, it will use Imagemagick to convert it to .png before saving it to a server. However it can only use the .tmp file from the HTML form, so it has to convert the CONTENTS while keeping the .tmp (and its filename) intact. This is my code so far:
if (exif_imagetype($tmpName) != IMAGETYPE_PNG) {
$uploadOk = 0; // don't upload later
$im = new Imagick("$tmpName");
$im->setImageFormat( "png" );
file_put_contents($tmpName, '');
file_put_contents(file_get_contents($im), $tmpName);
if (exif_imagetype($tmpName) != IMAGETYPE_PNG) { //check again
// try again or throw error somehow?
} else {
$uploadOk = 1;
}
} else {
$uploadOk = 1;
}
How do I properly use Imagick to convert the contents of my temp file into a png version of the original (non png) image?
EDIT: It could also be that the script should work fine, and the problem is something entirely different. Not sure at this point.
if you are to use, IMAGICK library, then you can use something like this:
...need to explain how you get the .tmp file, which I guess by using a form on your site... so...
.. get the post file
// This equals to 'some/server/path/temp/filename.tmp'
$original_image = $_FILE['tmp_name'];
// Lets work on the Imagick...
$img = new Imagick($original_image);
$img->setImageBackgroundColor('white');// red, black..etc
$img = $img->flattenImages(); // Use this instead.
$img->setImageFormat('png');
$new_image_name = 'nice_image_name.png';
$img->writeImage($new_image_name);
See if that works for you...
Related
I am in the process of writing an image upload script. I am adding lots of things e.g. store outside webroot and access through php script etc. One thing I have read to check is that a file is uploaded instead of an image. E.g. stop myimage.php.jpeg
I have written the following code to check it is an image file. Is this the best way to check this file has an image name?
$imagename= $_FILES['myimage']['name'];
//check there is only one fullstop in the imagename
if (substr_count($imagename,".")===1){
$imagesuffix = substr($imagename, strpos($imagename, ".") + 1);
//if image type is not a particular type of image
if($imagesuffix != "jpg"|| $imagesuffix != "png"||$imagesuffix != "jpeg"||$imagesuffix != "gif"){
echo"image filename is valid";
}
else{
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
}
}
else{
echo"this filename is invalid";
}
If your concern is to only allow uploads of files that are images, then you'll have to look at the file contents.
<?php
$image = 'image_file_to_test.png';
if (($imageInfo = getimagesize($image, $jpegInfo)) === FALSE)
die('Not an image.');
// OR
if (($imageType = exif_imagetype($image)) === FALSE)
die('Not an image');
If so desired, you can inspect either $imageInfo (docs) or $imageType (docs) to determine the image format. Please note that exif_imagetype() is the faster of the two, but it won't tell you as much as getimagesize().
I'm trying to create a simple thumbnail image and upload to server using imagick. The image is being selected via a form and I am able to get the thumb created via Imagick, however it is not saving to the right location.
When I use the below code, the image saves to the same directory as the page the code is on and includes the file path within the image name. For example "\images\myuploaded.jpg" as the file name.
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$errors = array();
if(preg_match("!image!", $_FILES['image']['type'])){
$image = $_FILES['image']['tmp_name'];
$imagethumb = new Imagick("$image");
$imagethumb->setImageFormat("jpg");
$imagethumb->thumbnailImage(100, 0);
$imgpath = "\images\\".$_FILES['image']['name'];
$imagethumb->writeImage($imgpath);
$_SESSION['message']=$image;
}else{
$errors['image'] = "You must select a .png, .jpg, or .gif images file.";
$_SESSION['message']=$errors['image'];
}
}
Thanks for any help.
_t
I am using Glide to deliver image content from one of my sites. This is working well and I have now built a file upload so that admins can upload images to the site for subsequent download.
Some of the images that admins will upload will be much larger than I need (or want the overhead of storing on the server), so I want to downsize them, preferably during the upload routine or failing that, just after they have been saved to their new location (storage/app/images)
So, I've been hacking around with intervention for instance without much success because of my poor understanding of the file names and paths available from getClientOriginalName/Extension etc.
Could anyone show me a pattern for this which would work well. Ideally I'd love to include something like I've seen on others' examples like...
$img = Image::make('foo.jpg')->resize(300, 200);
... in the correct place in my code
foreach($files as $file) {
$fileExtension = $file->getClientOriginalExtension();
$fileMimeType = $file->getMimeType();
if(in_array($fileExtension, $allowableExtensions)) {
if(in_array($fileMimeType, $allowableMimes)) {
array_push($dbFileList, $file->getClientOriginalName());
$newImage = '/images/' . $propertyCode . '/' . $file->getClientOriginalName();
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
}else{
$errorMessage = 'At least one file was not an image, check your results...';
}
}else{
$errorMessage = 'At least one file was not an image, check your results...';
}
}
Update 1:
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
$img = Image::make($file);
Storage::put('/images/new/' . $file->getClientOriginalName(), $img);
This updated code outputs the files to the /new directory and all looks fine, but the output files have 'zero bytes'. What am I missing?
Update 2: Final code
The final answer (after using the proper code provided by contributors) was that:
I had to move my app from virtual box on to the dev machine (iMac) to prevent extra confusion with paths
The path for the images must exist prior to making the ->save()
The path variable must be set in advance of the ->save()
I don't need the Storage::put at all, so the larger file never ends up on the server.
Then this final code started to work.
$path = storage_path('app/smallpics/')."/".$file->getClientOriginalName();
$img = Image::make($file)->resize(300,200)->save($path);
Much thanks to all of you. You make my Laravel learning curve a bit less terrifiying!!
You can use Intervention to manipulate your image (resize etc.) as
$new_image = Image::make($file)->resize(300,200)->save('/path/to/save');
The image upload and resize work flow is like:
Upload the image from tmp to your directory.
Make a copy of that image by setting the height, width, quality and save it in the same or some other directory.
Delete the original image.
So as per your code flow:
Storage::put('/images/' . $propertyCode . '/' . $file->getClientOriginalName(), file_get_contents($file));
after this code, put the image compress code and after that delete the original image.
you can use Intervention or just use imagemagick convert command line command for resize or convert.
Pay attention to comments :
public function saveUploadPic(Request $request)
{
$pic = $request->file('<NAME_OF_FILE_INPUT_IN_HTML_FORM>');
#check for upload correctly
if(!$pic->isValid())
{
throw new Exception("IMAGE NOT UPLOADED CORRECTLY");
}
#check for mime type and extention
$ext = $pic->getClientOriginalExtension();
$mime = $pic->getMimeType();
if(!in_array($mime, $allowedMimeTypeArray) || !in_array($ext, $allowedExtArray))
{
throw new Exception("This Image Not Support");
}
#check for size
$size = $pic->getClientSize() / 1024 / 1024;
if($size > $allowedSize)
{
throw new Exception("Size Of Image Is More Than Support Size");
}
########################YOU HAVE TWO OPTION HERE###################
#1- save image in a temporary location with random hash for name if u need orginal image for other process
#below code save image in <LARAVEL_APP_PATH>/storage/app/tmp/pics/
$hash = md5(date("YmdHis").rand(1,10000));
$pic->storeAs('tmp/pics', $hash.'.'.$ext);
#Then resize or convert it
$img = Image::make(storage_path('app/tmp/pics/'.$hash.'.'.$ext))->resize(300, 200);
#save new image whatever u want
$img->save('<PATH_TO_SAVE_IMAGE>');
#after u finish with orginal image delete it
Storage::delete(storage_path('app/tmp/pics/'.$hash.'.'.$ext);
#2- Or just use below for resize and save image witout need to save in temporary location
$img = Image::make($pic->getRealPath())->resize(300,200);
$img->save('<PATH_TO_SAVE_IMAGE>');
}
if you want to use convert see this link.
I want to return an image over an URL like http://placehold.it/500x500.
I have my URL http://example.inc/assets/image/35345, which calls an action on controller. The controller get some data (name, id, etc.) from database and also a binary string of the image content.
On the frontend site, i have my img tag, where i want to call the url in my src attribute.
<img src="http://example.inc/assets/image/35345">
Some more information, i use slim PHP Framework and my server is an ubuntu 13.x system (vagrant etc.). I am an typically frontend developer and dont have good skills # PHP.
Following snippets works:
$file = fopen($name, 'wb');
fwrite($file, $binaryData);
fclose($file);
but I dont want to generate files in a directory. Is this possible?
EDIT: Content-Type and Content-Length Headers are set, that is not the problem.
Grab the contents of the image, base_64 encode it, then return a a base64 image.
$file = file_get_contents($name);
list($width, $height, $type, $attr) = getimagesize($file);
echo '<img src="data:image/'.$type.';'.base64_encode($file).'"/>';
You should upload images in directory by using something like this. This code will upload your image in directory.
if ($_FILES['file']['name'] != "") {
$filename = $_FILES['file']['name']; //getting name of the file from form
$filesize = $_FILES['file']['size'];
$info = new SplFileInfo($filename);
$ext = $info->getExtension();
$filesize1 = ($filesize * .0009765625) * .0009765625;
if (!($ext == 'jpg' || $ext == 'png' || $ext == 'jpeg')) {
//set some error message and redirect
}
if ($filesize1 >= 5.0) {
//set message image size should be less than 5 mb
}
$target_path = $_SERVER['DOCUMENT_ROOT'] . "../images/profile_images/";
move_uploaded_file($_FILES['file']['tmp_name'], "$target_path" . $_FILES['file']['name']) or
die("Could not copy file!");
}
Insert image name(with extension) in database.($filename here)
Fetch image name from database and store in variable($profile_image here),use it in img src.
<a href='../images/profile_images/$profile_image'><img alt='Avatar' src='../images/profile_images/$profile_image'></a>
You can use only Anchor tag to redirect user on image in another tab in browser.
hope this answer will help you.
Because i had an mssql database with iso charset i have converted all of my results to utf-8, the problem was, that the bytestring also converted to utf-8.
after non converting the bytestring i also returned the bytestring and set the header content type to image/extension
Please can someone help? I have the following code which uploads a file to my server and renames it to whoever the logged in user is. For example the user 'coca-cola-lover' uploads a jpeg - the script would also rename the jpeg 'coca-cola-lover.jpg'.
My problem is that I need it to limit the upload to just jpegs - and also limit the file size to 2mb.
Please help - I was trying to find a solution all night.
Thanks in advance
// Your file name you are uploading
$file_name = $HTTP_POST_FILES['ufile']['name'];
$username = $row_Recordset1['username'];
$ext = end(explode('.', $file_name));
$renamed_file_name = $username;
$new_file_name=$renamed_file_name.'.'.$ext;
//set where you want to store files
//in this example we keep file in folder upload
//$new_file_name = new upload file name
//for example upload file name cartoon.gif . $path will be upload/cartoon.gif
$path= "../sites/images/users/".$new_file_name;
if($ufile !=none)
{
if(copy($HTTP_POST_FILES['ufile']['tmp_name'], $path))
{
echo "Successful<BR/>";
//$new_file_name = new file name
//$HTTP_POST_FILES['ufile']['size'] = file size
//$HTTP_POST_FILES['ufile']['type'] = type of file
echo "File Name :".$new_file_name."<BR/>";
echo "File Size :".$HTTP_POST_FILES['ufile']['size']."<BR/>";
echo "File Type :".$HTTP_POST_FILES['ufile']['type']."<BR/>";
}
else
{
echo "Error";
}
}
getimagesize tells you what format the file is in
as per bgy's comment, you should also force the file extension to be what you want:
$new_file_name=$renamed_file_name.'.'.$ext; // wrong, uses data from the client
$new_file_name=$renamed_file_name.'.jpg'; // ok, just what we want
never trust and never use filenames provided by the client.
I would recommend exif_imagetype:
<?php
if (exif_imagetype('image.gif') != IMAGETYPE_GIF) {
die(The picture is not a gif');
}
For details see here: http://php.net/manual/en/function.exif-imagetype.php
You can use any of the four to detect a mimetype of the file:
finfo_open (by default enabled as of 5.3)
getimagesize (requires enabled GD)
exif_imagetype (requires enabled Exif)
mime_content_type (deprecated as of 5.3)
You can also limit the MimeType from the FileUpload element, but since this is client-side code, it can easily be removed by malicious users (and it's also buggy across browsers):
<input type="file" name="picture" id="picture" accept="image/jpeg"/>
For further information on how to handle file uploads with PHP (including limiting file size), check the manual.
There is also a lot of very similar questions on Stack Overflow already, one being:
Check picture file type and size before file upload in php
You restrict the size via the normal mechanisms, but you'll need to use the fileinfo functions to determine the filetype after uploading.
A few advices for the current code
Use $_FILES instead of $HTTP_POST_FILES.
If you need to get file extensions use $extension = pathinfo($filename, PATHINFO_EXTENSION);.
Use is_uploaded_file and move_uploaded_file.
Don't relay on $_FILES['file']['type'] - it can be modified by user.
Indent your code.
If you want to limit file upload to the following requirements:
Filesize: max 2mb.
File type: image/jpeg
Do something like that:
$tmpName = $_FILES['file']['tmp_name'];
if (file_is_uploaded($tmpName) {
$filesize = fielsize($tmpName);
$mimeType = exif_imagetype('image.gif');
if ($filesize <= 2 * 1024 * 1024 && $mimeType == IMAGETYPE_JPEG) {
$filename = $USERNAME . '.jpg';
if (move_uploaded_file($tmpName, $filename) == false) {
// sth goes wrong
}
} else {
die('Invalid.');
}
}