PHP - Store Images in SESSION data? - php

Can you store an image in a PHP SESSION ?
I have a multi-step registration process using PHP on my site. On one of the steps, the users can upload their company logo (image).
The last step is to process their credit card.
So before I write any images to the web server and image location to the database, I want to make sure their credit card is valid and process.
As such, is it possible to temporarily store that image data in the SESSION variable?
If not, how else do people temporaily store image data on forms before committing that data?

You can but expect memory usage of your session to increase depending on the size of the images. In order to do so, you must save the file contents into a session variable.
If it is in session data and you have multiple steps after the upload the image will be reloaded (into the session) every page view until the steps are complete.
I would personally recommend against using the session for holding a binary file. Saving the image on disk into a temporary location until the registration is complete. I would only save the path to the temporary file in session. When the transaciton is completed move it to a proper location and do your db inserts.
Also, in essence, session data is stored on disk (or db) anyway so you might as well save the image file once then issue a move command once complete.

I'd save the file to disk, you could even name it using the user's session id. Then there could be some sort of clean up script which is run as a cron job and deletes the images of people who never successfully paid.
If you try and store an image in the session, you're doing it wrong.

When a file is uploaded, it gets assigned a temporary name in the $_FILES array. I don't know the exact lifespan of those files, but you might be able to capture that name in the session and put off the move_uploaded_file() call until after the CC is verified.
Or, you could do the CC step first.

Yes, you can store an image in a PHP session. Get it into PHP as a string (i.e. binary data) and then you can put it in the session.
You will want it to only be as big as it needs to be and you need to delete it as soon as you don't need it because large pieces of information in the session will slow down the session startup.

Sometimes We need to preview/confirm page before save data into database.
But Image file to the confirm page is a little bit differnt.You cant do
$_SESSION['s_name'] = $_FILES['f_name'] coz SESSION just keep the text file.
In the alternative way keeping file contents/binary value in session.
$_SESSION['obj_image_session'] = file_get_contents($_FILES['image_name']['tmp_name']);
$file= "new_file.jpg";
$fp=($file,"w");
fwrite($fp,$_SESSION['obj_image_session']);

If you have to keep the data, I would suggest keeping it as base64_encoded string. You can directly send base64_encode image data to the browser.
If I'd be in similar situation i would have rather saved the image and kept the information about the image in session/db. If for some reason the registration fails, i would unlink the file later. and occasionally run cron jobs to locate missing links with the images.
But i will really suggest you to stick to the second option and avoid the hassle altogether.

You can store image data in session as base encoded one easily. In production server you are supposed to have enough RAM.
My application needed upto 40MB of 4 images/apps for update and change before putting in mongoDB.
(Base encoding makes 1.3 times larger image size.)
$tmpNameSS1 = $_FILES["screenshot1"]["tmp_name"];
$fp = fopen($tmpNameSS1, 'r');
$rawDataSS1 = fread($fp, filesize($tmpNameSS1));
fclose($fp);
$SS1FileName = $_FILES["screenshot1"]["name"];
$encodedSS1Data = base64_encode($rawDataSS1);
registry::update('sCreateSS1Name', $SS1FileName);
registry::update('sCreateSS1Data', $encodedSS1Data);
A case will be: you have multiple image to uploaded and both client and server validation for size and type. It is faster to fetch from session.
After putting in DB null the variable holding the image.
Browser will show show that image with:
<img src="data:image/;base64,<?php echo registry::get('sCreateSS1Data'); ?>"/>
You can update the session for the image with empty string after the code reaches the end of the block. Typical case is updating form field with validation and when the user wants to change the text. You also want to show what image was uploaded between those failed updates. If you want to save the round trip (advisable) keep data for some moments in the session and empty that value after code is about exit.

when you put a file type in your form, you need to use the global variable Files
form.html
<form action="process.php" method="post" enctype="multipart/form-data">
<label for="picture">Picture:</label>
<input type="file" name="picture" id="picture"><br>
<input type="submit" name="submit" value="Upload">
</form>
process.php
<?php
session_start();
//make sure you have created the **upload** directory
$filename = $_FILES["picture"]["tmp_name"];
$destination = "upload/" . $_FILES["picture"]["name"];
move_uploaded_file($filename, $destination); //save uploaded picture in your directory
$_SESSION['user_name6'] = $destination;
header('Location: display_picture.php');
?>
display_picture.php
<?php
session_start();
?>
<div>
<img src="<?php echo $_SESSION['user_name6']; ?>" alt="picture"/>
</div>

Related

How to avoid duplicate file upload but keep the uploader unaware of it?

First of all, I apologize if the question is not clear, I'm explaining it below.
For every file uploaded, I'm renaming the file and recording the hash values (using sha1_files function, please suggest if there are some better or faster hashing techniques for the file in php) in a separate DB table and checking the hash of every new file to avoid duplicate files.
In this manner, the one uploading a duplicate file will get an error msg and the file won't be uploaded.
My question is, is there any techniques or algorithm by which I can prevent duplicate file upload but the duplicate file uploader will be unaware of it and will find the file in his/her account with a different name than the one already present. However, users won't be able to upload banned files by any means.
Yes, you should use xxhash which is much faster than sha1.
According to their benchmarks:
The benchmark uses SMHasher speed test, compiled with Visual 2010 on a
Windows Seven 32-bits box. The reference system uses a Core 2 Duo
#3GHz
SHA1-32 is 0.28 GB/s fast, and xxHash is 5.4 GB/s.
The PHP library is only getting a string as input, so you should use the binary library, and have something like this in your PHP:
list($hash) = explode(" ", shell_exec("/path/to/xxHash/xxhsum " . escapeshellarg($filePath)));
echo $hash;
Installing xxhash:
$ wget https://codeload.github.com/Cyan4973/xxHash/tar.gz/v0.6.3 -O xx.tar.gz
$ tar xvzf xx.tar.gz
$ cd xxHash-0.6.3; make
Just add some extra logic in your code possibly using an extra table or extra fields in the existing table (it is up to you, there is more than one way to do it) that saves the file to an alternate location should you discover it is a duplicate rather than sending an error. Not sure, though, if what you are doing is a good idea from the UI design point of view, as you are doing something different with the user input in a way that the user will notice without telling the user why.
Use an example like this to generate your sha1 hash client side before upload.
Save all your uploaded files with their hash as the filename, or have a database table which contains the hash and your local filename for each file, also save file size and content type.
Before upload submit hash from client side to your server and check for hash in database. If its not present then commence file upload. If present then fake the upload client side or whatever you want to do so the user thinks they have uploaded their file.
Create a column in your users table for files uploaded. Store a serialised associative array in this column with hash => users_file_name as key=>value pairs. Unserialize and display to each user to maintain their own file names then use readfile to serve them the file with the correct name, selecting it server side using the hash
As for your URL question. Create a page for the downloads but include the user in the url as well, so mysite.com/image.php?user=NewBee&image=filename.jpg
Query the database for files uploaded by NewBee and unserialize the array. Then:
$upload = $_GET['image'];
foreach($array as $hash => $filename){
if($filename == $upload)
$file = $hash;
}
Seach database for the path to your copy of that file, then using readfile you can output the same file with whatever namme you want.
header("Content-Description: File Transfer");
header("Content-type: {$contenttype}");
header("Content-Disposition: attachment; filename=\"{$filename}\"");
header("Content-Length: " . filesize($file));
header('Pragma: public');
header("Expires: 0");
readfile($file);
You could create an extra table which links files uploaded (so entries in your table with file hashes) with useraccounts. This table can contain an individual file name for every file belonging to a specific user (so the same file can have a different name per user). With current technologies you could also think about creating the file hash in the browser via javascript and then upload the file only if there isn't already a file with that hash in your database if it is you can instead just link this user to the file.
Addition because of comment:
If you want the same file to be accessible through multiple urls you can use something like apache's mod_ rewrite. I'm no expert with that but you can look here for a first idea. You could update the .htaccess dynamically with your upload script.

How to show image hidding its direct link in php?

How can I create a php code that will process an ID for example and return corresponding image without providing client with actual image hotlink.
As implemented on link below the image is displayed in html page, but the hot link is hidden from client. Even opening the image in new window same link is shown not the original link to image.
This is definitely not implemented in .htaccess file as for each image URL with id corresponding image is rendered and is not a redirect to a single page.
http://www.imagesup.net/?di=15140291437113
a basic way could be something like this
<?php
// query to database mabye?
$myPath = getImagePath($_GET['id']);
// what kind of image file is that?
$contentType = getContentType($myPath);
// read file content
$img = file_get_contents($myPath);
// here you tell the browser what kind of image is that e.g. jpeg,png,gif...
header("Content-Type: $contentType");
echo $img;
?>
you need to define getImagePath and getContentType functions according to your needs.
Whenever a surfer enters one of my websites, I always assign a session to him. The session holds a couple infos, for example: agent, IP, language, date, … etc., and gets passed along via cookie or via GET (as parameter to each one of my pages).
Since I deal with a lot of image content, I started databasing my collection. Which basically means that for administration and clustering purposes, I am saving all my images to a SQL database which is multi-homed and spread accross several servers. One could argue if that is a smart thing to do, but we can argue that on another day and in another article.
I wrote a little script which is used throughout my site:
<img src="http://example.com/display.php?id=34" border="0" alt="" />
With an ever changing ID of course. That’s the part referencing my images in the database.
The following is the code from the script which I use to retrieve the image from the database:
<?php
$connection=#mysql_connect(...);
#mysql_select_db(...);
$query="SELECT mime, file FROM images
WHERE id=".$_GET["id"];
$rawdb=#mysql_query ($query,$connection);
if($rawdb AND #mysql_num_rows($rawd-->0){
$array=# mysql_fetch_array($result);
if (!empty($array["fileContents"])){
// Output the MIME header
header("Content-Type: ".$array["mime"]}");
// Output the image
echo $array["file"];
}else{
// something else...
}
#mysql_free_result($rawdb);
}else{
// something else...
}
#mysql_close($connection);
?>
Since I already have a session for each user that comes to my website, I just added the following:
<img src="http://example.com/display.php?id=34&sid=383829" border="0" alt="" />
And implement a small session checkup in the script itself:
<!--
session_start();
if($_SESSION["is_known"]){
// do database calls
}else{
header("Location:http://mydomain.tld/dontsteal.html");
}
-->
The main advantage to my method is, that the session is entirely server side. A user can not rid himself off it, or fake information. Since I have a timeout and save all the necessary info (IP!) to validate against, it looks pretty perfect to me and fit my needs.
One of the setbacks here are resources and performance. But since I am not forcing you, you may test and evaluate. Hope that helps!
Create a php script which you use as src in the img tag.
In that script get the data from the image with file_get_contents. Then send the header with the right mime type. For example header('Content-type: image/jpeg'); Then output the data.

Display user input image without saving it to a folder

How can I display an image and pass it as an input parameter in an executable in php without saving the image in a folder. The user gives the image path as input and I am using ajax to display the image when it is selected when I save it to a folder it works but how can I display it without saving it in a folder? My code now is
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$_FILES["file"]["name"]);
//echo "Stored in "."upload/".$_FILES["file"]["name"];
echo "<img src='upload/".$_FILES["file"]["name"]."' class='preview'>";
I tried
<img src=$_FILES["file"]["tmp_name"]. class='preview'>
but it didnt work. As I will have thousands of input from thousands of user I dont want to save it. Is there any optimised and efficient method to do this?
I think, its not possible to show image without saving it. You could try to save the image in temp folder on the server side and clean this folder periodically to avoid much space consumption.
The src attribute of the <img> tag should be an URL accessible by the client.
You try to give a local path (ex: path/to/your/file.jpg) of a temporary file as URL, it will not working.
info: The uploaded image is save on the local disk on a temp directory, and could be deleted by PHP later.
If you want to show the image without moving it at a place reacheable by a URL, you can try to load its content as base64 content
$imagedata = file_get_contents($_FILES["file"]["tmp_name"]);
$base64 = base64_encode($imagedata);
and use in your HTML
<img src="data:image/png;base64, <?php echo $base64; ?>" />
I don't think you can show the image without saving it.
You need to save the file either to the filesystem or to memory if you want to later output
Your problem here is that $_FILES only exists in the script that the image was sent to. so when you initiate another http request for img source, php no longer has any clue what file your trying to read.
You need a way to tell which image to be read on http request.
One thing you can do is that you can save the file in a place accessible by the client and then just have php delete it after you output it. So once the image is outputted it will be deleted and no longer be existing in the file system.
Another approach would be to get the image from the memory by directly writing the contents to httpresponse.
You can do this way
$image = file_get_contents($_FILES["file"]["tmp_name"]);
$enocoded_data = base64_encode($image);
and when you show your image tag :
<img src="data:image/png;base64, <?php echo $enocoded_data ; ?>" />
Hope any of these helps you

Codeigniter | Save Base64 image to file

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.

What is the "conventional" way of handling uploaded image names?

So im making a website with an image upload functionality and im storing the image name to the database. I took a screenshot of my mac and wanted to upload this photo "Screen shot 2011-02-18 at 6.52.20 PM.png". Well, thats not a nice name to store in mysql! How do people ususally rename photos in such a way that each photo uploaded has a unique name? Also, how would i make sure i keep the file extension in the end when renaming the photo.
I would drop the extension, otherwise Apache (or equivalent) will run a1e99398da6cf1faa3f9a196382f1fadc7bb32fb7.php if requested (which may contain malicious PHP). I would also upload it to above the docroot.
If you need to to make the image accessible above the docroot, you can store a safe copy that is ran through image functions or serve it from some PHP with header('Content-Type: image/jpeg') for example and readfile() (not include because I can embed PHP in a GIF file).
Also, pathinfo($path, PATHINFO_EXTENSION) is the best way to get an extension.
Ensure you have stored a reference to this file with original filename and other meta data in a database.
function getUniqueName($originalFilename) {
return sha1(microtime() . $_SERVER['REMOTE_ADDR'] . $originalFilename);
}
The only way this can generate a duplicate is if one user with the same IP uploads the same filename more than once within a microsecond.
Alternatively, you could just use the basename($_FILES['upload']['tmp_name']) that PHP assigns when you upload an image. I would say it should be unique.
Hash the image name. Could be md5, sha1 or even a unix timestamp.
Here is an (untested) example with a random number (10 to 99)
<?php
function generate_unique_name($file_name)
{
$splitted = split(".", $file_name);
return time() . rand(10,99) . "." . $splitted[count($splitted)-1];
}
?>
You could use an image table like:
id: int
filename: varchar
hash: varchar
format: enum('jpeg', 'png')
The hash can be something like sha1_file($uploaded_file) and used to make sure duplicate images aren't uploaded. (So you could have multiple entries in the image table with the same hash, if you wanted.) The id is useful so you can have integer foreign key links back to the image table.
Next store the images in either:
/image/$id.$format
or
/image/$hash.$format
The second format via the hash would make sure you don't duplicate image data. If you are dealing with lots of images, you may want to do something like:
/image/a/b/c/abcdef12345.jpg
where you use multiple layers of folders to store the images. Many file systems get slowed down with too many files in a single directory.
Now you can link to those files directly, or set up a URL like:
/image/$id/$filename
For example:
/image/12347/foo.jpg
The foo.jpg comes from whatever the user uploaded. It is actually ignored because you look up via the id. However, it makes the image have a nice name if the person chooses to download it. (You may optionally validate that the image filename matches after you look up the id.)
The above path can be translated to image.php via Apache's MultiView or ModRewrite. Then you can readfile() or use X-SendFile (better performance, but not always available) to send the file to the user.
Note that if you don't have X-SendFile and don't want to process things through PHP, you could use a RewriteRule to convert /image/$hash/foo.jpg into /image/a/b/c/$hash.jpg.

Categories