I have a form to upload a picture file, but i want to include an option to rotate the image in the same form.
What im not sure of, is should i rotate the image before saving it, or save it, open it, rotate it, then save it again. Im not sure what is the best method for accomplishing this. The code im using is below:
$imagename = uniqid().".jpg";
if (file_exists("upload/" . $imagename))
{
//echo $_FILES["file"]["name"] . " already exists. ";
} else {
// Rotate image here before saving?
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $imagename);
// Or open/rotate/resave image here?
}
Always move the image first, then manipulate it. There are security restrictions in PHP that make it possible for a system administrator to say that only the move_uploaded_file() function is able to access an uploaded file in the temporary location and no other functions.
So, move it first, then manipulate. Otherwise your script will not work on servers that have this security enabled.
There is no real right or wrong answer here in my opinion. However I could see you running into issues with attempting to perform image manipulation on a tmp file (folder/file permissions, etc.).
Therefore you should move the image first, then after it is moved perform any image manipulation on it. This will help guarantee that you have the proper permissions to perform the image manipulation.
Basically when the picture is uploaded, it is already saved to a tempoary location. So either way you will open, rotate and save it. If it does not serve any purpose to save it to your local folder first, I would recommend to just open the temporary file, rotate it and save it.
Related
I am using plupload to upload file in my php based website, with large file uploading the file becomes a file named 'blob' without any suffix. I know this is a binary file that contains the raw data, question is how to retrieve the data and save it back as an image file, say .png/.jpg or etc? I tried:
$imageString = file_get_contents($blogPath);
$image = imagecreatefromstring($imageString);
But it gives me some 'Data is not in recognized format...' error, any thoughts? Thanks in advance.
Your call to imagecreatefromstring() should work just fine if your file_get_contents() is working. Use var_dump($imageString) to verify. Did you mean to name your variable $blobPath instead of $blogPath?
You don't need to load this image though. Just rename the file.
rename($blobPath, 'new/path/here.jpg');
http://php.net/manual/en/function.rename.php
I am storing the uploaded image files for late use, like attaching them to posts or products(my site is e-commerce CMS). I figured that my image file didn't get fully uploaded to the server, the image before upload is 6mb, but the blob file is just 192kb, so my best guess is that what get uploaded is just a chunk instead of the whole package, and yet that brought up another question: how should I take all the pieces and assemble them as one complete image file? As mentioned earlier, I am using plupload for js plugin and php as backend, the backend php code to handle uploading goes like this:
move_uploaded_file($_FILES["file"]["tmp_name"], $uploadFolder . $_FILES["file"]["name"]);
Instead of doing that you should do this to display image to the browser
<img src="data:image/jpeg;base64,'.base64_encode( $row['blob_image'] ).'"/>
I'm not sure what imagecreatefromsting does or how it encodes the image.
I looked at the documentation for that function; you're missing:
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data); <--- this operation
I have created a custom product configurator that saves a canvas element as a base64 encoded image. When I echo the image in the browser as the image src it works fine.
So something like this works:
$base64Image = $_POST['dataUrl'];
echo '<img src="'.$base64Image.'" />';
My problem is that codeigniter wont add this base64 image src to the session, probably because its too big. I have tried some methods that people have used to write an image to the server and they all throw errors. Does anyone know how I can write this base64 string to an image on the server like 'myimage.png' in the images/custom folder?
Any help is appreciated.
You can also use
$decoded=base64_decode($base64Image);
file_put_contents('newImage.JPG',$decoded);
Reference Link: http://j-query.blogspot.in/2011/02/save-base64-encoded-canvas-image-to-png.html
Use tempnam() to get a unique file name in a directory writable by the script. You can map a session variable "thisUsersTempFile" to that file name.
Or you can store the association somewhere else if it is not temporary. If you need to clean up the tmp files, you would probably need to do that since I don't think you can hook the session destruction. You could poll for existing sessions and delete the tmpfiles associated with the sessions that were destroyed. You could use a cron job for that.
After doing research, I found that it is more recommended to save the image name in database and the actual image in a file directory. Two of the few reasons is that it is more safer and the pictures load a lot quicker. But I don't really get the point of doing this procedure because every time I retrieve the pictures with the firebug tool i can find out the picture path in the file directory which can lead to potential breach.
Am I doing this correctly or it is not suppose to show the complete file directory path of the image?
PHP for saving image into database
$images = retrieve_images();
insert_images_into_database($images);
function retrieve_images()
{
$images = explode(',', $_GET['i']);
return $images;
}
function insert_images_into_database($images)
{
if(!$images) //There were no images to return
return false;
$pdo = get_database_connection();
foreach($images as $image)
{
$path = Configuration::getUploadUrlPath('medium', 'target');
$sql = "INSERT INTO `urlImage` (`image_name`) VALUES ( ? )";
$prepared = $pdo->prepare($sql);
$prepared->execute(array($image));
echo ('<div><img src="'. $path . $image . '" /></div>');
}
}
One method to achieve what you originally intended to do by storing images in database is still continue to serve image via a PHP script, thus:
Shielding your users from knowing the actual path of an image.
You can, and should have, images stored outside of your DocumentRoot, so that they are not able to be served by web server.
Here's one way you can achieve that through readfile():
<?php
// image.php
// Translating file_id to image path and filename
$path = getPathFromFileID($_GET['file_id']);
$image = getImageNameFromFileID($_GET['file_id']);
// Actual full path to the image file
// Hopefully outside of DocumentRoot
$file = $path.$image;
if (userHasPermission()) {
readfile($file);
}
else {
// Better if you are actually outputting an image instead of echoing text
// So that the MIME type remains compatible
echo "You do not have the permission to load the image";
}
exit;
You can then serve the image by using standard HTML:
<img src="image.php?file_id=XXXXX">
You can use .htaccess to protect your images.
See here:
http://michael.theirwinfamily.net/articles/csshtml/protecting-images-using-php-and-htaccess
I'm also working on a project which stores the url path of images on the database (Amazon RDS) and the actual images in a cloud managed file system in Amazon S3.
The decision to do so came primarily with the concern of price, scalability and ease of implementation.
Cheaper: Firstly, it is cheaper to store data in a file system (Amazon S3) compared to a database (Amazon EC2 / RDS).
Scalable: And since the repository of images may grow pretty big in the future, you might also need to ensure that you have the adequate capacity to serve them. On this point, it is easier to scale up a filesystem compared to a database. In fact, if you are using cloud storage (like Amazon S3), you don't even need to worry about having not enough space as it has been managed for you by Amazon! you would just need to pay for what you use.
Ease of Implementation: In terms of implementation, storing images in a file system is much easier. If you were to serve images directly from databases, you would probably need to implement additional logic to convert blob files into html src blob strings to serve images. And from the look of it, this might actually take up quite substantial processing power which might slow your web server down.
On the other hand, if you were to use a filesystem, all you would require is to put down the url path of the image from the database to the src attribute of the image and its all done!
Security: As for security of the images, i have changed the image name to a timestamp concatenated with a random string so that it will prove really difficult for someone to browse for pictures without knowing the file name.
ie. 1342772480UexbblEY7Xj3Q4VtZ.png
Hope this helps!
NB: Please edit my post if you find anything wrong here! this is just my opinion and everyone is welcome to edit!
For an image file (JPEG) that has been uploaded to the server via a PHP script (to a directory such as http://www.somedomain.com/images, is it a good idea to allow the client to get the image's direct address (such as http://www.somedomain.com/images/someimage.jpg and paste it into a WYWSIWYG text editor (such as TinyMCE)?
I am wondering if there is a preferable method where the direct address is encrypted?
Please, if I should just link directly to the image, just say so.
Thanks!
Note: I have modified this question from my original. Please see revisions if you are curious, but I think I was asking the question incorrectly. My apologies to the people who already answered.
As long as you check correctly WHAT is being uploaded, it shouldn't be a problem. So please at least use getimagesize or a similar function to make sure it's an image that's being uploaded, AND make sure the extension on the file is correct so that it will never be run through the PHP interpreter - to prevent someone from uploading an image with a PHP script attached.
BTW Here's a nice whitepaper on uploads and security : http://www.scanit.be/uploads/php-file-upload.pdf
Depending on the CPU Constraints of your web-hosting service you can write a service to 'serve' the images to your users.
Here is some very BASIC code, it needs spiffing up and cleaning up for XSS/etc...
<?php
$basePath = "/path/to/my/image/store/not/web/accessible/";
$file = NULL;
if (isset($_GET['file']))
$file = $_GET['file'];
if ($file != NULL)
{
$path = $basePath . $file;
// $file needs to be checked for people
// trying to hack you, but for the sake of simplicity
// i've left it out
$mime = mime_content_type($path);
$size = filesize($path);
header("Content-Length: " . $size);
header("Content-Type: " . $mime);
header('Expires: 0');
readfile($path); // Outputs the file to the output buffer
}
?>
Obviously you can put whatever security checks in here you want. But this way your files are below the web dir, and you can apply logic to thier accesibility. This is typically used more for FILE vs. Images, but you can do the same thing here.
Images Accessed like this
http://www.mysite.com/image.php?file=hello.jpg
And you can use mod_rewrite to rewrite urls like this:
`http://www.mysite.com/images/hello.jpg
Into the first url.
I Cannot stress enough the need for further security checking in the above example, it was intended to show you how to serve a file to the user using PHP. Please don't copy & use this verbatim.
Wordpress uses direct links for images. The permalink function simply puts the image on a page along with metadata for comments, but the images' SRC attributes still link directly to the image.
why are you concerned about revealing your image location. Hotlinking?
if so you can prevent hotlinking with htaccess
http://altlab.com/htaccess_tutorial.html
Didn't you get your answer already?
Every site reveals image location to the browser. It's just the way web works.
Got any reason to "encrypt" original location?
HI
I have a forum and I'm trying to think of how to do an "attachment" feature.
You know if you make a thread you can chose to upload a file and attach it in the thread.
Should I make a table called attachment with id of the file id in table files?? Whats the best way. And I want you to be able to upload more than 1 attachment. and if it's a picture show a little miniature of the picture.
How should I check if the file exist etc? How would you do this?
Sorry for my poor english
You question is too broad but I'll give you some pointers:
store the images on the disk, something like /uploads/--thread_id--/1.jpg, /uploads/--thread_id--/2.jpg and so on (this way you don't have to make any changes to your DB)
Regarding the upload process, validation and image resizing you can read more at (I recommend you read them in this order):
http://pt.php.net/manual/en/function.exif-imagetype.php -> image validation
http://php.net/manual/en/function.move-uploaded-file.php -> upload process
http://pt.php.net/manual/en/book.image.php -> image resizing & manipulation
Chacha's plan sounds good to me, but you have to be careful. Make sure the files that you save don't have any execution permissions and that the file isn't on a web-accessible directory on your server. I think you should put the upload directory in a directory higher than your web directory for security purposes.
Another possible way to save the files: save their binary code in blobs in the database. I'm not sure if there are any advantages to this method, but I haven't personally had to deal with file uploads.
Above all else, be careful with uploaded data!
I honestly would create a Column on the table of posts that says 'Attachments', and then do a comma delimited string of attachment file names
file1.png,file2.png,file3.png
then when you get it into PHP, simply explode it
$attachments = explode(',', $string);
and check for each file that you have already put in your upload directory:
foreach($attachments as $file)
{
if(!is_file($upload_directory.$file))
{
$error[] = $file . " is not a valid attachment";
// run cleanup script
}
}
To get the attachments, it is really simple code, but you need to validate and sanitize the incoming file.
foreach($_FILES as $array)
{
// Sanitize Here
die("SANITIZE HERE!");
move_uploaded_file($array['tmp_name'], $upload_dir);
}