Friday, June 1, 2007

Image upload and preview without a page refresh

Whenever I am asked to develop a page where content needs to be fed without a refresh, I think of AJAX. And whenever I think of Asynchronous Javascript and XML; my stomach rolls over and my eyes bulge out !!! I've been writing web apps using AJAX for more than 2 years now; but somehow I never happen to get it right in the first shot.

So, I was sitting glumly, readying myself to drum out that javascript code; when Swapna looked across my shoulder and said,
"You don't NEED ajax for that !!!"
"Huh??? You don't?"
"No... The older technologies are good enough !!!"

Yup !!! I was as surprised as you too. Let me tell you what I learnt from her.

Suppose you want to build a simple application with an image upload functionality, and you want to display the uploaded image in the preview screen soon as it is uploaded. Now, how do you do this without AJAX? With some smart programming, of course.

Let's see how...

First, you will have to have a control which will allow you to upload the image to the server.

<form name="frmUpload" id="frmUpload" enctype="multipart/form-data" action="ImageUploadView.php?strAction=upload" target="_blank" method="POST">
<h1>Test Page For file upload and access the file on the current page</h1>
<input name="strUpload" id="strUpload" type="file" value="Select Image"><br/> <br/>
<a href="javascript:void(0);" onclick="javascript:UploadImage();">Click to upload image</a>
<br />
<br />
<img id="imgUpload" name="imgUpload" src="x.jpg">
</form>



Next, we define a Javascript function UploadImage(), that will submit to the same PHP file, but in a new window.

// description : upload the image to the server
// notes : 1. open a new window
// 2. submit the form to it

function UploadImage()
{
window.open("","upload_image");
document.getElementById( 'frmUpload' ).target="upload_image";
document.getElementById( 'frmUpload' ).submit();
}



We also define another Javascript function, whose purpose is to reset the source of the image on the current page.

// description : set the src of the image to the uploaded one
function SetImageFile( pImgSrc )
{
document.getElementById( 'imgUpload' ).src=pImgSrc;
}



The image upload request is handled on the server. At the server end, we throw Javascript code that calls the function SetImageFile().
**Please note that the script will require write permissions to the directory it's residing in.**

<?php
$imagename = uniqid('ff') . ".jpg";


// move (actually just rename) the temporary file to the real name.
// write permissions are required by the script to place the image here.
move_uploaded_file ( $_FILES['strUpload']['tmp_name'], $imagename );

print ( "<script type=\"text/javascript\">" );

if(file_exists($imagename) && $_FILES['strUpload']['name'] != '')
{
print ( "self.opener.SetImageFile(\"" . $imagename . "\");" );
}

print ( "window.close();" );
print ( "</script>" );
?>


And Viola !!! The uploaded image is displayed in the page without needing a refresh.

What are we doing here? We are -
  • submitting the FORM to the server.
  • at the server, we store the image.
  • we then print javascript which is actually calling the javascript functions residing in the parent document.
  • which then, replaces the image source.
The full code is given below. Copy the code into a file, say, ImageUploadView.php, and check it out.

<?php
// file name : ImageUploadView.php
?>
<html>
<head>
<title>Image Upload and Preview without Page Refresh</title>
<script type="text/javascript">

// description : upload the image to the server
// notes : 1. open a new window
// 2. submit the form to it
function UploadImage()
{
window.open("","upload_image");
document.getElementById( 'frmUpload' ).target="upload_image";
document.getElementById( 'frmUpload' ).submit();
}

// description : set the src of the image to the uploaded one
function SetImageFile( pImgSrc )
{
document.getElementById( 'imgUpload' ).src=pImgSrc;
}

</script>
</head>
<body>

<?php
// case : show the FORM, by default
if( !isset($_REQUEST['strAction']) || $_REQUEST['strAction'] == "" )
{
?>
<form name="frmUpload" id="frmUpload" enctype="multipart/form-data" action="ImageUploadView.php?strAction=upload" target="_blank" method="POST">
<h1>Test Page For file upload and access the file on the current page</h1>
<input name="strUpload" id="strUpload" type="file" value="Select Image"><br/> <br/>
<a href="javascript:void(0);" onclick="javascript:UploadImage();">Click to upload image</a>
<br/>
<br/>
<img id="imgUpload" name="imgUpload" src="x.jpg">
</form>
<?php
}

// case : upload the file
else
{
$imagename = uniqid('ff') . ".jpg";

// move (actually just rename) the temporary file to the real name.
// write permissions are required by the script to place the image here.

move_uploaded_file ( $_FILES['strUpload']['tmp_name'], $imagename );

print ( "<script type=\"text/javascript\">" );

if(file_exists($imagename) && $_FILES['strUpload']['name'] != '')
{
print ( "self.opener.SetImageFile(\"" . $imagename . "\");" );
}

print ( "window.close();" );
print ( "</script>" );
}
?>
</body>
</html>



Neat. Ain't it? No creating requests. No opening connections. No parsing responses. No cross-browser support headaches. No Nothing.

Just Plain Simple and Neat !!!

God give Swapna a long life !!!


8 comments:

Anonymous said...

Doesn't work in FF 3.0.6

Rithish said...

@anon : Is it so? thanks for pointing it out. Will check and make relevant changes.

Anonymous said...

Doesn't work at all in any browser for me. Post good code or don't post at all.

Rithish said...

I tried it on FF 3.0.6; and it works perfectly fine.

Do you hit any errors when you try it out?

Also note that the script will require write permissions to the directory it's residing in.

If you still encounter issues, then you can mail me directly to rithish_at_gmail_dot_com, and Iwould be glad to assist.

Rithish said...

Have also tried it on IE 5.5 / 6 / 7; and all work well.

Anonymous said...

I test your codes and it work perfectly but I think the page refreshes as soon as I click upload. Anyway thanks for sharing...

Gerard said...
This comment has been removed by the author.
Gerard said...

i have a better solution,

just use filesize () php function to get filesize and load the image

just put at the end of the image filename the size of the filename

like this :

images.jpg?356412

it work perfectly, for me the best solution, i've been looking for something better, but i don't find better, this is a simple solution and easy changes for a big website

you can find a example source code working in this forum :

http://www.php-forum.com/phpforum/viewtopic.php?f=13&t=11828