Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Brendon Bauer

macrumors 6502
Original poster
May 14, 2007
344
0
Good 'ol USofA
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.
 
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?
 
Brendon - were you able to fix the problem?

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

Thanks,
Jay
 
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
 
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
 
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");

?>
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.