File Upload script hangs on Safari?

Discussion in 'Web Design and Development' started by Brendon Bauer, Mar 21, 2009.

  1. macrumors 6502

    Joined:
    May 14, 2007
    Location:
    Good 'ol USofA
    #1
    I have taken bits and pieces of an upload script to upload files to my server, but it seems like every browser works fine except Safari. It's like a 50/50 chance that Safari will hang or upload it successfully. I'm dealing with 10-20mb files and so it's not fun to sit around for 5 minutes and then realize it wasn't working. I've tested with 200kb files so I know in a matter of seconds whether it worked or not. When it doesn't work and just is "loading" if I click upload again, it will work. I was wondering if maybe you could spot my problem in the code:

    Here is the form:
    Code:
    <html>
    <title>File Upload</title>
    <script type="text/javascript">
    <!--
    	function toggle_visibility(id) {
    	   var e = document.getElementById(id);
    	   if(e.style.display == 'block')
    		  e.style.display = 'none';
    	   else
    		  e.style.display = 'block';
    	}
    -->
    </script>
    </head>
    <body>
    
    <h2>File Upload</h2>
    
    <?php
    	error_reporting(0);
    	$errors = array();
    	$mm = $_GET['mm'];
    	$dd = $_GET['dd'];
    	$yy = $_GET['yy'];
    	$date = $mm."/".$dd."/".$yy;
    ?>
    		
    <br /><p>Date: <?php echo $mm."/".$dd."/".$yy; ?><br /><br /><i>(The audio sermon must be an mp3 file under 20MB in size)</i></p>
    
    <p><form enctype="multipart/form-data" action="audio_sermon_2a.php" method="POST">
    
    	<input type="hidden" name="MAX_FILE_SIZE" value="21000000" />
    	<input type="hidden" name="year" value="<?php echo "20".$yy; ?>" />
    	<input type="hidden" name="mm" value="<?php echo $mm; ?>" />
    	<input type="hidden" name="dd" value="<?php echo $dd; ?>" />
    	<input type="hidden" name="yy" value="<?php echo $yy; ?>" />
    
    	Choose a sermon file to upload: <input type="file" name="file" size="30" /><br /><br /><br />
    
    	<div class="buttons"><button type="submit" name="submit" onclick="toggle_visibility('loadinggif');" class="positive"><img src="/images/icons/tick.png" alt="" /> Upload Sermon</button></div><br /><br /><br />
    </form></p>
    <div id="loadinggif" style="margin: 0; padding: 0; display: none;"><p><table border="0"><tr><td><img src="/images/loading.gif" alt="loading..." /></td><td valign="middle">  Uploading... please be patient...</td></tr></table></p></div>
    
    </body>
    </html>
    That page takes a date passed to it via get and uses it to choose the location and filename for uploading.

    Here is the actual uploader:
    Code:
    <?php
    // ==============
    // Configuration
    // ==============
    error_reporting(0);
    $uploaddir = "path_to_location_hidden_just_because/".$_POST['year']; // Where you want the files to upload to - Important: Make sure this folders permissions is 0777!
    $allowed_ext = "mp3"; // These are the allowed extensions of the files that are uploaded
    $max_size = "21000000"; // 50000 is the same as 50kb
    $max_height = ""; // This is in pixels - Leave this field empty if you don't want to
    $max_width = ""; // This is in pixels - Leave this field empty if you don't want to upload images
    // Check Entension
    $extension = pathinfo($_FILES['file']['name']);
    $extension = $extension['extension'];
    $allowed_paths = explode(", ", $allowed_ext);
    for($i = 0; $i < count($allowed_paths); $i++) {
    	if ($allowed_paths[$i] == "$extension") {
    		$ok = "1";
    	}
    }
    
    // Check File Size
    if ($ok == "1") {
    	if($_FILES['file']['size'] > $max_size) {
    	print "<font color=\"red\">The sermon is too big! It can't be bigger than 20mb. Try making it smaller, <a href=\"#\" onclick=\"history.go(-1);return false;\">go back</a>, and upload it again.</font>";
    	exit;
    	}
    
    	// Check Height & Width
    	if ($max_width && $max_height) {
    		list($width, $height, $type, $w) = getimagesize($_FILES['file']['tmp_name']);
    		if($width > $max_width || $height > $max_height) {
    			print "File height and/or width are too big!";
    			exit;
    		}
    	}
    
    	// The Upload Part
    	if(is_uploaded_file($_FILES['file']['tmp_name'])) {
    		move_uploaded_file($_FILES['file']['tmp_name'],$uploaddir.'/'.$_POST['mm'].".".$_POST['dd'].".".$_POST['yy'].".mp3");
    	
    		print "<meta http-equiv=\"Refresh\" content=\"0; url=path_to_page_on_successful_upload?mm=".$_POST['mm']."&dd=".$_POST['dd']."&yy=".$_POST['yy']."\">";
    		
    	}
    	
    } else {
    	print "<font color=\"red\">You must select a file to upload and it must be an mp3 file (ends in '.mp3'). Fix this, <a href=\"#\" onclick=\"history.go(-1);return false;\">go back</a>, and try uploading again.</font>";
    }
    ?>
    Unfortunately I can't allow access to this page for security reasons so you can't really test it. Just hoping you can see the problem :). I removed a couple of file locations above...

    Thanks.
     
  2. macrumors member

    Joined:
    Aug 9, 2004
  3. thread starter macrumors 6502

    Joined:
    May 14, 2007
    Location:
    Good 'ol USofA
    #3
    Interesting... Thanks for the response!

    I tried adding
    Code:
    <script type="text/javascript">
    /* A pretty little hack to make uploads not hang in Safari. Just call this
     * immediately before the upload is submitted. This does an Ajax call to
     * the server, which returns an empty document with the "Connection: close"
     * header, telling Safari to close the active connection. A hack, but
     * effective. */
    function closeKeepAlive() {
      if (/AppleWebKit|MSIE/.test(navigator.userAgent)) {
        new Ajax.Request("/ping/close", { asynchronous:false });
      }
    }
    </script>
    within the head section of the page with the form, and
    Code:
    onsubmit="closeKeepAlive();"
    to the form tag, making it
    Code:
    <form enctype="multipart/form-data" action="audio_sermon_2a.php" onsubmit="closeKeepAlive();" method="POST">
    This didn't seem to fix the problem though... It will still hang on about 50% of my attempts to upload a small file. Did I implement the "hack" or fix wrong? Or is that what they were implying on airbladesoftware website you gave as an example? As a note, I'm using Safari 4 beta, but I did uninstall the beta earlier to test the latest nonbeta version of Safari with the form (not with this hack applied, though) and it hung as well. I assume it shouldn't make much of a difference with the beta version? In other words I haven't tested this hack with nonbeta Safari, but I have tested the form w/out the hack with nonbeta Safari (which occasionally hung as well).

    Any idea what's up?
     
  4. macrumors newbie

    Joined:
    Dec 1, 2009
    #4
    Brendon - were you able to fix the problem?

    I'm heading down the same path, and haven't worked it out yet.

    Thanks,
    Jay
     
  5. thread starter macrumors 6502

    Joined:
    May 14, 2007
    Location:
    Good 'ol USofA
    #5
    Jay,

    I never did find a fix to the problem... so instead I put a warning note next to the uploader for those using safari. Sorry I couldn't help you!

    Brendon
     
  6. macrumors newbie

    Joined:
    Dec 1, 2009
    #6
    Ok - thanks.

    I'll post if I eventually get something to work reliably... (ugh)

    --Jay
     
  7. macrumors newbie

    Joined:
    Dec 1, 2009
    #7
    Got it to work.

    A couple of noob mistakes:

    1) Ajax.Request is found in prototype.js (Google it), and needs to be included.
    2) "/ping/close" needs to be an empty file accessible by the server. I'm using Django, so I put it in a directory along with other statically served files. My path isn't "/ping/close", so I needed to change it (e.g. "/media/close").

    Now when I watch the TCP packets between the browser and the server, I can see the connection close. Safari file uploads seem to be working properly (it's an intermittent problem, so I wouldn't put money on it yet...).

    Hope this helps,
    Jay
     
  8. macrumors newbie

    Joined:
    Jun 15, 2010
    #8
    Safari Hangs on PHP upload script

    I am having the same problem. I have a very simple php upload script but after one or two iterations of the upload, the page just sits there.
    If I click "submit" again it completes.
    This script works in Firefox without failure, haven't tested anything else.
    But I see there are more than one reports of this same behavior.
    If anyone solves it I'd like to know.

    Here's the whole script:
    Don't laugh, I'm just at testing stage when I noticed this bug with Safari.
    If it's my script, PLEASE let me know.

    Thank you

    <?php

    session_start();


    $target_path = "/var/www/uploads/";
    $target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

    if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
    //echo "The file ". basename( $_FILES['uploadedfile']['name']). " has been uploaded";
    } else{
    // echo "There was an error uploading the file, please try again!";
    }


    $_SESSION['thefileweuploaded'] = basename( $_FILES['uploadedfile']['name'] );
    $_SESSION['project_description'] = $_POST['project_description'];
    $_SESSION['job_details'] = $_POST['job_details'];

    $duhname = $_SESSION['thefileweuploaded'];

    //echo "Updating your upload: Don't click anything until this message changes!";


    // redirect page to upload confirmation page
    if( $_SERVER['SERVER_ADDR'] == "::1" ) {
    $url = "http://localhost/index.html?page=upload/upload_confirmation.html&uploadedfile=$duhname";
    } else {
    $url = "http://" . $_SERVER['SERVER_ADDR'] . "/index.html?page=upload/upload_confirmation.html&uploadedfile=$duhname";
    }
    header("Location: $url");

    ?>
     

Share This Page