Friday, June 06, 2014

FTP File transfer using PHP

Couple of times I have faced situations where I need to backUp all files on a server and shift to another. This becomes tedious if it is done through normal FTP clients like FileZilla or CuteFTP etc because file downloading to your local machine and uploading to the target server may take several hours. Or, if we try to download and upload via CPanel, it will take same amount time and there will be additional risk of breaking of download/upload if network connection is lost for any reason.

To avoid this huge time wastage, we can do the following things ::

1. Use CPanel to ZIP all the source files in Source server
2. Then Upload a small PHP file to Source server and run it
3. This PHP file uploads the big backup ZIP archive to the Target server through FTP
4. On the Target server, we unzip the ZIP archive 

What we would require ::

1. CPanel access of both the source and target servers
2. FTP access of target server

So, the process is pretty simple, the important part is to write the PHP file which does the main job. 

Check the PHP code below.

First we use ftp_connect() function to connect to Target server, if this connection is not established, we don't proceed further.

Secondly, use use ftp_put() function to upload the file to Target from Source server.


<?php
/// FTP Uploader Application

/// SET FTP Login details for Target Server
$ftp_server = "targetserver.com"; 
$ftp_user_name = "ftpUserName";
$ftp_user_pass = "ftpPassword";

// set up the FTP connection
$conn_id = ftp_connect($ftp_server) or die("Could not FTP Connect to $ftp_server"); 

// login with FTP username and password
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass); 

// check connection
if ((!$conn_id) || (!$login_result)) 

   echo "<br><span style='color:red'>FTP connection has failed!</span>";
   exit; 

else 
{
   echo "<br>Connected to <b>$ftp_server</b>, for user <b>$ftp_user_name</b>";
}

// GET the file, which needs to be transferred
$source_file = "public_html.tar.gz";

// Set the TARGET location
$destination_file = "public_html/public_html.tar.gz";

// upload the file
$upload = ftp_put($conn_id, $destination_file, $source_file, FTP_BINARY); 

// check upload status
if (!$upload) 

   echo "<br><span style='color:red'>FTP upload has failed!</span>";

else 
{
   echo "<br>Uploaded [$source_file] successfully to <span style='color:green'>$ftp_server</span> as [$destination_file]";
}

// close the FTP stream 
ftp_close($conn_id); 
?>

The above code is quite self-explanatory. 

There are some other FTP functions like as shown below :;

Connection Related ::
ftp_ssl_connect() :- For making Secure SSL-FTP connection
ftp_pasv()  :- Set PASSIVE mode to ON/OFF

File/Folder Edit/Delete/Rename ::
ftp_get() :- Download a File from the Target Server 
ftp_mkdir()  :- Create new folder on Target server
ftp_rmdir()  :- Remove folder from Target server
ftp_rename()  :- We can rename old folders/files on the Target server 
ftp_delete()  :- Delete a file from the Target server

Browse the Target Server :
ftp_chdir() :- Change directory
ftp_pwd() :- Get current directory in the Target server
ftp_nlist() :- Returns a list of files in the given directory

Some examples ::
ftp_chdir($conn_id,"public_html");
ftp_get($conn_id,'Ro_bo_ts.TxT','robots.txt',FTP_ASCII);

The above 2 lines, changes current directory to 'public_html' and downloads a file 'robots.txt' in ASCII mode and saves it as 'Ro_bo_ts.TxT' on local directory.

print_r(ftp_nlist($conn_id,'public_html'));
The above line Get listing of all the folders/files inside 'public_html' folder.

Wednesday, May 14, 2014

Include the text "Grand Total to be Charged" in Invoice Emails in Magento 1.7

I had this requirement in Magento 1.7 a couple of days back. Suppose, my site has multiple currencies and I check out with GBP whereas my default currency is USD. Now, the Order email has the following texts ::

...                          ... 
Grand Total                  £93.66
Grand Total to be Charged    $169.70

Which means, I purchased items costing £93.66 but I will be charged $169.70 (which is equal to £93.66 as per conversion rate on that day). But when the Invoice mail is generated, the last line "Grand Total to be Charged" is not appearing. I needed that line to appear on all other transaction emails including Invoice emails.

How I found the solution ?

To solve the problem, I started digging into the email template files first. Order_new.html and invoice_new.html were the files I started to delve in. My observations are as shown below :

1. The Invoice email template invoice_new.html has the following line ( which deals with and prints the whole PRICE stuffs ):
     
    {{layout handle="sales_email_order_invoice_items" invoice=$invoice order=$order}}

   whereas the Order email template order_new.html has the following line :

   {{layout handle="sales_email_order_items" order=$order}}

2. In sales.xml, layout handle 'sales_email_order_invoice_items' has a block template 'email/order/invoice/items.phtml'. This item.phtml file has the following line ::

    echo $this->getChildHtml('invoice_totals');

and sales.xml again says ( getChildHtml('invoice_totals') is referring to )::
   
    <block type="sales/order_invoice_totals" name="invoice_totals" template="sales/order/totals.phtml">   

3. Again, in sales.xml, layout handle 'sales_email_order_items' has a block template 'email/order/items.phtml' .. this item.phtml file has the following line ::

   echo $this->getChildHtml('order_totals');

and sales.xml again says getChildHtml('order_totals') is referring to ) :: 
   
<block type="sales/order_totals" name="order_totals" template="sales/order/totals.phtml">

4. So, both Order and Invoice emails dynamically loads "sales/order/totals.phtml" file. Now in totals.phtml file, we have a line like this :: 

foreach ($this->getTotals() as $_code => $_total): 

The above foreach construct takes output (as an array) from getTotals() function and loops through the output array containing whole Pricing structure including base price, shipping expenses, tax, discounts, Base price in other currencies etc. 

5. As the Base Price (with BASE currency as set in Admin Panel ) was coming properly in Order email, I checked the class ( from <block type='sales/order_totals' ) Mage_Sales_Block_Order_Totals found in Mage/Sales/Block/Order/Totals.php. The getTotals() function is just iterating the class property '$this->_totals'. I also checked how this '$this->_totals' array was created through '_initTotals()' method. And within this '_initTotals()' method, $this->_totals['base_grandtotal'] is being created which is responsible for printing the Order price in Base Currency and this is what I was looking for. However, this Base price was not coming in Invoice emails. Hence I opened the Class 'Mage_Sales_Block_Order_Invoice_Totals'.

6. The class 'Mage_Sales_Block_Order_Invoice_Totals' ( existing in file 'app/code/core/Mage/Sales/Block/Order/Invoice/Totals.php' ) inherits from the class 'Mage_Sales_Block_Order_Totals' and overrides the function _initTotals() which created the pricing array _totals. Check the function below :

    protected function _initTotals()
  {
     // Call Parent Mage_Sales_Block_Order_Totals
     // class' _initTotals() to create the 
     // parent class' _totals array
     parent::_initTotals();
        
     // Removing the _totals['base_grandtotal']
     $this->removeTotal('base_grandtotal');
     return $this;
  }
    
    The line $this->removeTotal('base_grandtotal'); is removing the Base Price section from the _totals array. Simply commenting the line finally solved my problem.

Magento 1.8 Notes - III

1. Get Customer's FirstName in transactional Emails in Magento ::
    
    In transactional email template files ( order_new.html/invoice_new.html etc), the following line
   
   Hello, {{htmlescape var=$order.getCustomerFirstName()}}
   
   should give the customer first name. However, in email templates (order_new.html etc) where "Hello, {{htmlescape var=$billing.getName()}}" is used, replacing this with the above mentioned "{{htmlescape var=$order.getCustomerFirstName()}}" may give full name of the  customer. In such situations, the following method would always work.
   
   The class Mage_Sales_Model_Order is defined in app\code\core\Mage\Sales\Model\Order.php file where getCustomerName(), getCustomerFirstName() etc functions are defined. We can add our own method inside this class.
   
   public function getCustomerOnlyFirstName()
 {
   // GET Name
   $name = trim($this->getCustomerName());
 
   // Find if any Space is there within Name
   $pos = strpos($name," ");
 
   // If Space is found, extract till that Space
   if($pos !== false) 
   {
     $name = trim(substr( $name, 0, $pos ));
   }
 
   // return 
   return $name;
 }
   
   and then use the line below to get the customer's first name in email templates ( where $order variable is used ) ::
   
   Hello, {{htmlescape var=$order.getCustomerOnlyFirstName()}}

2. Include Customer IP address in New Order Email template ::
   
   To achieve this, we need to follow steps shown below --
   a. Modify /public_html/app/code/core/Mage/Sales/Model/Order.php
   b. We need to edit the function sendNewOrderEmail()
   c. We nee add a new variable 'remoteaddr' or anything of our choice and set some value to it.
   
   $mailer->setTemplateParams(array(
       'order'        => $this,
       'billing'      => $this->getBillingAddress(),
       'payment_html' => $paymentBlockHtml,
       'remoteaddr'   => $_SERVER['REMOTE_ADDR']
     ));
   
 d. Now we must call the variable from within template file as {{var remoteaddr }}   

3. Get Order Comments in Transaction Email :: 
   
     Use the below line to get Customer Comments in Email Template :-
   
     {{var order.getEmailCustomerNote()}}

4. Run Installation process again : 
   
   Once, I forgot the Admin Password on Local installation of Magento, I wanted to restore it. I thought that it would be better if I could run the Installation process again. Running the Installation process again did not delete my existing data on Database. Which means it did not create new tables on the DB rather used the old ones. So my Admin Panel was intact. 
   
   To go through install wizard again, we need to delete app/etc/local.xml file and reload any magento page, it will be redirected to /install. 

5. Magento Error :: "There was a problem with the subscription: This email address is already assigned to another user."
   
   This is not a bug but an intended behaviour in Magento. This message can be seen in the following scenarios ..
   
   i. When the user is not logged in, however he/she is using an email address with which another customer is already registered.
   ii. When the user is logged in, however he/she is not using his/her own email address, rather an email address with which another customer is already registered.
   
   So, if we use a right email address, this error message can be avoided.
   
6. Get the GIANT XML file programmatically which is created after every module's config.xml file is parsed by Magento and included in the global config. 
   
   echo Mage::app()->getConfig()->getNode()->asXML() ;

Tuesday, April 29, 2014

Arrays in PHP - 2

In my previous article Arrays in PHP, I had discussed about creating and printing arrays. In this article, I would discuss some more things we can do with Arrays. But before that, let's check one complex array below :

<?php

$arr = array (
          
'name'      => 
   array('first_name'  => 'Robin', 
         'middle_name' => '', 
         'surname'     => 'Smith'),
'dob'       => '14/Jan/1980',
'lucky_nos' => array( 
         'numerology_based'    => 1, 
         'chinese_astro_based' => 2 ),
'grade_years' => array( 
         '2001' => 'A+', 
         '2002' => 'B+', 
         '2003' => 'C+' ),
'ph_nos'    => array(
         '2202-3256', 
         'father' => '4545-2256')
);

?>

In the above multi-dimensional associative array, a student info has been stored under various "key" => "value" pair combinations.

Now, if we want to add some more information to it, we would do it the following way.

<?php
$arr['favourite_color'] = array('blue','pink') ;
?>

So, a new key 'favourite_color' will be created holding an array of 'blue' and 'pink'. But, if we do it the following way ::

<?php
$arr[] = array( 'favourite_color' => array('blue','pink') ) ;
?>

next available index 0 (Zero) will be created. So all the indices within the array will be 'name', 'dob', 'lucky_nos', 'grade_years', 'ph_nos' and 0 (zero). It is same as writing the following statement (in this context)::

<?php
$arr[0] = array( 'favourite_color' => array('blue','pink') );
?>

In case of Associative arrays, the keys would have automatically casts to Integers as shown below :

<?php
$arr = array (  
        0     => 'Philippe',
        '0'   => 'John',  // String to Integer 0
0.9   => 'Mick',  // Float to Integer 0
false => 'Andrew', // 'false' is cast to Integer 0
NULL  => 'Rahman' // NULL is cast to '' 
       );

print_r( $arr );
?>  

All the index '0' (as string), '0.9' (as float/double), 'NULL' (as NULL), 'false' (as boolean) will be converted to integer 0. In case of floating point number, the fractional part is totally discarded, hence, for example, '1' will be accepted as key for given keys like '1.23', '1.67' or '1.09'. In our example above, first four keys are evaluated to 0 (zero) and hence $arr[0] will have the last value 'Andrew' as every time old value is overwritten. The key 'NULL' is cast to empty string. Check out the output below :

Array
(
    [0] => Andrew
    []  => Rahman
)
  
Copying an array to another is very simple. All the 'key'=>'value' combination are preserved while copying to another array.

<?php
// Simple copy
$arr2 = $arr;
?>

However, if we create a reference to that array, any changes to original array would reflect in the reference. Check the example below.

<?php
// Create a reference
$arr3 = & $arr;
?&gt;

Next, we would work on some array operators. Let's start with '+' operator, which unions two array. Check the example below.

<?php
// First array : index 0,1
$arr1 = array( 1, 2 );

// Second array : index 0,1
$arr2 = array( 2, 3 );

// Add them using '+' operator
// $arr1 if first operand
print_r( $arr1 + $arr2 );

// $arr2 is first operand
print_r( $arr2 + $arr1 );
?>

The output will be

Array ( [0] => 0 [1] => 1 )
Array ( [0] => 2 [1] => 3 )

In case of $arr1 + $arr2, as the $arr2 also has index '0' and '1', $arr1's (former array) values will be preserved. Hence the first print_r() print's $arr1's values.

But in case of $arr2 + $arr1, the second print_r() prints just the opposite as first operand $arr2's values are preserved. Check another example ::

<?php
// both the Arrays have indices 0 and 1
$arr1 = ('apple','banana');
$arr2 = ('mango','orange');

// Outputs array(0=>'apple', 1=>'banana')
print_r( $arr1 + $arr2 );
?>

Here the first array - $arr1's index/value pairs will be preserved as the second array also has the same indices.

If both the arrays have different key=>value combinations, the resultant array can have all the key=>value combinations as shown in the example below ::

<?php
// First array : index 0,1
$arr1 = array( 1, 2 );

// Second array : index 2,3
$arr2 = array( 2=>2, 3=>3 );

// Add them using '+' operator
// $arr1 if first operand
print_r( $arr1 + $arr2 );

// $arr2 is first operand
print_r( $arr2 + $arr1 );
?>

Here is the output

Array ( [0] => 1 [1] => 2 [2] => 2 [3] => 3 )
Array ( [2] => 2 [3] => 3 [0] => 1 [1] => 2 )

In the first case, $arr2's index and value combinations are appended to $arr1's same combination whereas in the second case, $arr1's key value pairs are appended to $arr2's same pairs.

Next, we can use operators '==', '<=', '>=' for array comparisons. Keys should match on both the arrays for such comparison. Array with lesser number of values are smaller in case of comparison. If keys are same, then values are checked. Check the example below :

<?php
$arr1 = array ( 1=>1, 2=>2 );
$arr2 = array ( 2=>2, 3=>3 );

// Uncomparable as index don't match
echo $arr1 == $arr2;

$arr1 = array ( 1=>1, 2=>2 );
$arr2 = array ( 1=>2, 2=>4 );

// $arr2 has larger values
echo $arr1 <= $arr2; // Outputs 1
?>

Let's see how to deal with situations where a function returns an array.

<?php
// Define a Function which returns array
function return_array(){ return array(1,2,3,4); }

// As of PHP 5.4, access the 3rd element
$fourth_elem = return_array()[3];

// Otherwise, store it in some
// other variable
$arr = return_array();

// Access Array Items
$fourth_elem = $arr[3];
?>


Objects and other data types can be typecast to array. Check out some examples below : 

<?php
class a
{
  private $name = 'Robin';
  private $age  = 15;
  public  $roll = 1;
  protected $ph = 909090;
}

// Create Object of class a
$obj = new a();

// Object to Array
$arr = (array) $obj ;

// Member names will be the 
// KEYS in the resultant array
print_r( $arr );

// String to Array
$name = 'Robin' ;
$arr = (array) $name;
print_r( $arr );
?>

While typecasting from Object, the member variables' names become the keys of the resultant array. For private variables, class is prepended to the key, for public variables the key is same as the variable name, for protected variable a '*' is prepended to the key. The characters/strings which are prepended to the key are wrapped by NULL (\0)  characters. These NULL characters can be seen if we var_dump() the array.

Check the output of the above code :

Array
(
    [aname] => Robin 
    [aage] => 15
    [roll] => 1
    [*ph] => 909090
)
Array
(
    [0] => Robin

)

Arrays types are very flexible in PHP. We would discuss more on it in later articles.

Thursday, April 03, 2014

Creating Image Upload Previewer with Javascript/PHP

This is a very common scenario on Web Applications that an user selects an image for uploading and he is shown the preview of that image immediately before the user clicks on the "Submit" button. 

How is it possible when the image file is not even uploaded to Server? From where the <img> element is showing the right image? How is it happening without refreshing the page?

Actually this involves both Server and Client side interactions which is the subject matter for this discussion. 

We have the following screen, 





and it changes to this immediately after the user selects an image from his Hard Disk.




To achieve our goal, let's chalk out the essential points : 

1. We need an <input type="file"> element within a <form> element.
2. The <form> element must be submitted for uploading/sending a file to Server. As form submission refreshes the page, we'll be using a little trick here.. we'll take help of an <iframe> element and submit our form onto this <iframe>. This will not refresh the page, but upload the file to the server.
3. When the image file is successfully uploaded, we just change the "src" property of an <img> element on our page to load the image and show the preview.

Let's check out the HTML we need.

<html>
<head>
<script src="jquery.min.js" ></script>
<script src="imageupload.js"></script>
</head>
<body>

<!-- FORM starts here -->
<form name="f" enctype="multipart/form-data" method="post" target="myiframe" action="imageupload.php">

Select Image files :: <br> <br>

<div style='padding-bottom:10px'>

<!-- FILE INPUT element -->
<input type="file" name = "file1" onchange="upload_and_show_image(this)"> 

<!-- <img> Tag to display the Preview -->
<img id='image1' border='0' src='' width="100" style='display:none'/> 

<!-- We have a SPAN element to show messages -->
<span id='message1'></span>

</div>

<!-- An Hidden Field -->
<input type='hidden' name='form_submit' value='1'>

</form>

<!-- THE IFRAME which is kept Hidden -->
<iframe name="myiframe" style="display:none"></iframe>

</body>
</html>

Notes : 
1. We have included JQuery Library for all our client-side working.

2. We have put all our client-side logic in imageupload.js file, which we'll be dissecting soon.

3. We have a Server Side PHP file imageupload.php where the form is actually submitted. This Server Side file handles the uploaded image and renames/stores it.

4. Check the declaration of <input> element :
   <input type="file" name = "file1" onchange="upload_and_show_image(this)"> 
   
   The javascript function "upload_and_show_image()" is called when user selects a new Image. We are capturing the "change" event on this element. The included script "imageupload.js" contents the whole upload_and_show_image() function definition.
   
5. Check the declaration of <iframe> element :
   <iframe name="myiframe" style="display:none"></iframe>
   
   We have given a name "myiframe" to it and it is kept hidden on our page.
   
6. Check the declaration of <form> element :
   <form name="f" enctype="multipart/form-data" method="post" target="myiframe" action="imageupload.php">
   
   For uploading a file, "enctype" property should have a value "multipart/form-data", "method" should be "post". The <form> will be submitted to a PHP page "imageupload.php". Check out its "target" property which holds "myiframe" i.e the <form> will be subitted to "imageupload.php" within an <iframe> having a name "myiframe". This way, ONLY the said <iframe> will be refreshed, not other parts of our page.
   
7. We have the <img> element which is kept hidden initially. When an Image is fully uploaded and available to browser for displaying, we change the "src" property of this element to load it on the browser.
   
   <img id='image1' border='0' src='' width="100" style='display:none'/> 
   
8.  We have a SPAN element where we can show error messages etc. 
    <span id='message1'></span>  

9. We also have a hidden value within the form. With this, we can track the form submission at the server end.
   
   <input type='hidden' name='form_submit' value='1'>
   

Let's check out the JS file "imageupload.js". What it does is shown point wise below :

1. Get the fileName. On some browser, we get whole path of the image like "c:\fakepath\sampleImage.jpg", we need to extract the name of only the image.

2. We would replace all the spaces with hyphens ("-") within the file name.

3. We also check for valid image extensions. If wrong files are selected, no preview will be available.

4. After we submit the form using Javascript, we create an Image object, load the image with it and when loading is completed, we change the "src" property of the <img> element on our page to show the preview.

Now the content ...

function upload_and_show_image(t)
{
  // Initially Hide the <img> element
  jQuery("#image1").hide();
  
  // get the Selected Image File's name 
  var filename = jQuery(t).val() ;
  filename = filename.toLowerCase()
  
  /// Take the actual File name
  /// Remove the path information 
  var pos = filename.lastIndexOf("\\");
  if(pos!= -1)
  {
    filename = filename.substr(pos+1);
  }
    
  // GET Extension
  var extn = filename.split('.').pop();
  
  // Remove all spaces with hyphens
  var fname = filename.split('.')[0].replace(/\s/g,"-");
  var filename_final = (fname + "." + extn);
  
  // Locate to the SPAN for a message
  var sp = jQuery("#message1");
  
  // Check for valid Image extension
  var valid_extn = ['jpg','jpeg','png','bmp','gif','tiff','wmf'];
  var matched = 0;
  for(var i in valid_extn) 
   if(valid_extn[i] == extn) matched = 1;
  
  if( !matched )
  {
     // Show an Error message in the SPAN element
     jQuery(sp).html("Please select a valid Image file").css("color","red");
     
     // RETURN
     return;
  }
  
  // Proceed, Clear the SPAN content
  jQuery(sp).html("");
  
  // Submit the form
  jQuery("form[name='f']").submit();
  
  // Create New Image  
  var i = new Image();
  i.src = filename;
  
  // Do some tasks when Image is loaded
  i.onload = function()
  { 
   // Change the 'src' property
   jQuery("#image1").attr("src", i.src);
 
    // Show the preview <img>
   jQuery("#image1").show();   
  }
  
}

The above JS code is quite self-explanatory. The input (type 'file') gets full path name usually like "c:\abcd.jpg" (On windows system) etc. So, we need to extract only the file name out of it. And here, the lastIndexOf() and substr() function helps us to achieve it.

var pos = filename.lastIndexOf("\\");
filename = filename.substr(pos+1);

Now check the Server side code for handling the Image upload. Here is the content of "imageupload.php" file. 
  
<?php
// Check whether form is submitted
if(isset($_POST['form_submit']))
{
  // Check if FILE has been uploaded
  if( isset($_FILES['file1']['tmp_name']) && $_FILES['file1']['error'] == 0 )
  {
    
// Get the filename corrected
$file_name = strtolower($_FILES['file1']['name']);
$a = explode(".", $file_name );
$name = str_replace(" ","-",$a[0]);
$extn = $a[1];

// Check for Valid extensions
   $extns = array('jpg','jpeg','png','bmp','gif','tiff','wmf');
    
// Found
if( in_array( $extn, $extns) !== false )
{
     // Upload
    @move_uploaded_file( $_FILES['file1']['tmp_name'], "$name.$extn");
}
  }
}
?>

The above piece of HTML, JavaScript and PHP codes work together to effect this Image preview. 

But there is a problem with the above working model. Check out this section in JS file:

  // Submit the form
 jQuery("form[name='f']").submit();
  
 // Create New Image  
 var i = new Image();
 i.src = filename;

Here, we are submitting the form and then immediately we are creating an Image object in Javascript and changing its "src" property. Problem is, the Server may be quite busy while processing the uploaded file, renaming it and moving it etc or Server is taking time as the image has huge file size. But client side javascript does not wait for the server side PHP to finish its own task. So, sometimes, the Image loading (changing the 'src' property of 'img' tag) is done when the Image was not even created/moved by PHP code. As a result, the  <img> element (meant to show the preview) does not show the image and we get an error message "Network Error : file not found"  in browser console. An broken Image icon is displayed on browser. However if you right click on the broken-image icon and click "Reload Image" for 1 or more times, the image is shown perfectly (by that time the Image is available at the server-end). To work around with this, we may follow the following logic :: 

1. Submit the form
2. Run a timer, which fires a JS function check_for_image_existence() every 100 miliseconds. This function fires an Ajax request to server to query whether the image file is now existing. So, every 100 milliseconds, an Ajax call is fired.
3. If the Ajax response is satisfactory (Image exists), then we change the "src" property of the <img> element on our page. 

To achieve this, we need to change our JS file first as shown below, We are showing only the updated lines: 

     // Submit the form
  jQuery("form[name='f']").submit();
  
  /*  COMMENT OUT OLD CODE
  var i = new Image();
  i.src = filename;
  i.onload = function()
  { 
jQuery("#image1").attr("src", i.src);
jQuery("#image1").show();   
  }
  */
  
  // SET a Timer
  timer = setInterval( function(){ check_for_image_existence(); }, 100);
  
  /// The function which fires AJAX
  function check_for_image_existence()
  {
      
    // Ajax Call
    jQuery.ajax({
url  : "imageupload.php",
data : "check_file_existence=1&filename=" + filename_final,
dataType : "json",
type : "post",
cache : 'false',
success : function(data)
{
      // Success
      if(data.success == 1 )
      {
       // Change the "SRC" property
       jQuery("#image1").attr("src", filename_final );
       jQuery("#image1").show(); 
 
       // Clear the Interval
       clearInterval( timer );
      }
}   // success callBack ends  
     }); // jQuery.ajax ends
  } // Function ends 

The ajax call sends request to a PHP file "imageupload.php" with parameters "check_file_existence" and "filename". When the return response holds a value of "1" in "data.success" variable, we know that the file is available in Server and changing "src" can not just fail. We also remember to clear the timer.

Check the new Server side PHP code which can be appended to the existing code in "imageupload.php".

<?php
if( isset($_REQUEST['check_file_existence']) && $_REQUEST['check_file_existence'] == 1 )
{
  // Extract File name from Ajax request
  $filename = $_REQUEST['filename'];
  
  // Check if file exists
  if($filename && file_exists($filename))
    echo json_encode(array("success" => 1));
  else
    echo json_encode(array("success" => 0));  
}
?>

We receive the ajax response in json format.

The above fixes make the whole solution work perfectly now. It runs on all browsers also. Give it a try.