PHP Upload Timeouts: More Efficient Upload Script? - php

I have written a pretty basic upload script that takes the file and uploads it using the standard move_uploaded_file method as you see below:
//UPLOAD IMAGE
$path = "../../clients/$realClient/" . $_FILES["image"]["name"][$x];
move_uploaded_file($_FILES["image"]["tmp_name"][$x], $path);
$displayPath = "private/clients/$realClient/" . $_FILES["image"]["name"][$x];
mysql_query("INSERT INTO images VALUES(NULL, '$displayPath', '$client', '$project', '$newWeight')") or die("Unable to Insert Image - Please Try Again");
echo "File Successfully Uploaded<br />";
This upload script works perfectly for most purposes. Here's my issue:
I have a standard shared hosting package so sometimes when the user tries to upload a file that takes over five minutes to upload (say a video or some other high res media), the server times out. The hosting company has said that as it's a shared hosting server they are unwilling to increase the timeout limit for me.
Is there a more efficient upload script that will allow files to go up in under five minutes or is there perhaps an alternative you could suggest?
Cheers,
Dan

The PHP script is run after the upload completes; so if there's a timeout during the upload, there's nothing you can do in the script (as it won't be run at all).
If the timeout occurs during the script, you could split it into multiple parts - have the first script just store the uploaded file and HTTP redirect to another, which will do the processing and database work. In the script you're showing, the processing seems simple enough, not sure if splitting that would help.
Assuming you're showing just a simplified version:
script1.php
// upload is complete
$fname= basename($_FILES["image"]["name"][$x]); //prevent directory traversal
$uniqid = uniqid("",true);
$path = "../../clients/$realClient/temporary/" . $uniqid . '/' . $fname;
// move to temporary location and redirect
move_uploaded_file($_FILES["image"]["tmp_name"][$x], $path);
header('Location: /script2.php?file=' . $uniqid . '/' . $fname);
script2.php
$path = $_GET['file'];
$uniqid = basename(dirname($path));
$fname = basename($path);
$temp_path = "../../clients/$realClient/temporary/" . $uniqid . '/' . $fname;
$final_path = "../../clients/$realClient/" . $fname;
move($temp_path,$final_path);
// do whatever processing is necessary
mysql_query("INSERT INTO images VALUES(NULL, '$displayPath', '$client', '$project', '$newWeight')") or die("Unable to Insert Image - Please Try Again");
echo "File Successfully Uploaded<br />";

Related

ftp_size returns -1 after a file is uploaded using curl

My script packs some files with ZIP then uploads this ZIP to another server. After the upload it checks size of the ZIP on the FTP and locally. If sizes are the same- the local ZIP is deleted.
The problem is ftp_size() returns -1. But only in the real script. In my test script it works fine.
Test script works like this:
$f = ftp_connect(HOST);
$res = ftp_login($f, USER, PASS);
$fname = 'archive_2018-09-18_13-39';
$fsize = ftp_size($f, "$fname-img.zip").'';
$fsize2 = filesize("backup/$fname-img.zip").'';
echo $fsize . '<br>' . $fsize2;
and it returns:
22907946995
22907946995
The real script works like this:
$f = ftp_connect(HOST);
$res = ftp_login($f, USER, PASS);
$fname = 'archive_' . date('Y-m-d_H-i');
exec("zip -r -0 backup/$fname-img.zip \"website\" 2>&1");
exec('curl -T "' . "backup/$fname-img.zip" . '" ftp://' . HOST . ' --user ' . USER . ':' . PASS . ' 2>&1');
$fsize = ftp_size($f, "$fname-img.zip").'';
$fsize2 = filesize("backup/$fname-img.zip").'';
echo $fsize . '<br>' . $fsize2;
and it shows:
-1
22907946995
Real script uploads file just fine. It just doesn't show correct size on the FTP server.
So it's not a problem with size of the file and not a problem with FTP connection.
Try moving ftp_connect only after the call to curl. There is possibly some caching involved that prevents the FTP server from returning correct size immediately, if the file is uploaded using a different connection.
Though I'd strongly suggest you to use PHP functions to upload the file.

Images are not shown and file name changes when uploaded to the database

I can't get the picture to display/show when viewing, although the files are already stored in the database (table 'menu') http://i.imgur.com/wo1w90H.png. Also when I upload the images all at once, their file name would change automatically. I don't know how and why this happens. I use array to upload multiple images.
if (isset($_POST["Submit"])) {
--some code here--
if (isset($_POST["id_list"])) {
// if id list available
foreach($_POST["id_list"] AS $id) {
--some code here--
/* Handle file upload */
if ($_FILES['upload']['error'][$id] == 'UPLOAD_ERR_OK') {
$path = "images/newmenu/";
$path_parts = pathinfo($_FILES["upload"]["name"][$id]);
$extension = $path_parts['extension'];
$picture = md5(uniqid()) . "." . $extension;
if (move_uploaded_file($_FILES['upload']['tmp_name'][$id], $path . "/" . $picture)) {
$update = " UPDATE menu
SET MenuPicture='$picture'
WHERE MenuID=$id";
$mysqli->query($update) or die(mysqli_error($mysqli));
}
}
}
}
}
}
Below is the form and yes it does include enctype="multipart/form-data"
<input type="file" multiple name="upload[' . $id . ']" value="' . $record["MenuPicture"] . '">
Filename changes because you are generating it this way
$picture = md5(uniqid()) . "." . $extension;
uniqid() is based on current time and hashing it will cause the filename to change everytime
When I upload the images all at once, their file name would change automatically
It was due to this:
$picture = md5(uniqid()) . "." . $extension;
// And later
move_uploaded_file($_FILES['upload']['tmp_name'][$id], $path . "/" . $picture)
Basically, you are moving your uploaded file to a new filename for your image file, which is generated using uniqid() and hashed with md5(), with the file extension appended at the end.
I can't get the picture to display/show when viewing
How are you trying to display the picture? Is it from web browser, or you go straight to the directory and open from there? What error(s) did you get, if any?
Actually, have you tried to go to the directory and see whether the file is created inside the images/newmenu/ directory?
Also, for the target upload directory, you might want to append it with $_SERVER['DOCUMENT_ROOT'] so that the target directory is not dependent on where your script is located, but it's always based on the root.
By the way, you might know already, but there is an entry in PHP manual page on uploading multiple files

Retrieve original uploaded filename using php on OpenShift

I would like to check that a file uploaded to my OpenShift app has a text extension (.txt or .tab). Following some advice given here I wrote the following code, with echoes added to help debug:
$AllowedExts = array('txt','tab');
echo "AllowedExts: " . $AllowedExts[0] . " and " . $AllowedExts[1] . "<br>";
$ThisPath = $_FILES['uploadedfile']['tmp_name'];
echo "ThisPath: " . $ThisPath . "<br>";
$ThisExt = pathinfo($ThisPath, PATHINFO_EXTENSION);
echo "ThisExt: " . $ThisExt . "<br>";
if(!in_array($ThisExt,$AllowedExts) ) {
$error = 'Uploaded file must end in .txt or .tab';
}
echo "error echo: " . $error . "<br>";
On uploading any file, the echoed response was:
AllowedExts: txt and tab
ThisPath: /var/lib/openshift/************/php/tmp/phpSmk2Ew
ThisExt:
error echo: Uploaded file must end in .txt or .tab
Does this mean that OpenShift is renaming the file upon upload? How do I get the original filename and then check its suffix? More generally, is there a better way to check the file type?
$_FILES['uploadedfile']['tmp_name'] contains the name of a temporary file on the server (which can be moved with move_uploaded_file()). If you want to check the original name of the uploaded file on the client machine use $_FILES['uploadedfile']['name'].
That's not an Open Shift issue, it's the standard way of PHP.
For further details see http://php.net/manual/en/features.file-upload.post-method.php
For other ways to detect the file type see http://php.net/manual/en/ref.fileinfo.php

Warning: move_uploaded_file(): it is moved but the Filesize stays at zero

I have been using an upload script on my server, like below
$newname = time() . '_' . $_FILES[$file]["name"];
if (strtolower(end(explode('.', $_FILES[$file]["name"]))) != 'pdf' AND $file != "damage_attachment_damageform_1" AND $file != "damage_attachment_damageform_2" AND $file != "damage_attachment_damageform_3" AND $file != "damage_attachment_damageform_4") {
if (move_uploaded_file($_FILES[$file]["tmp_name"], $_SERVER['DOCUMENT_ROOT'] . '/components/com_fleet/uploads/docs/' . $newname)) {
$images[] = $_SERVER['DOCUMENT_ROOT'] . '/components/com_fleet/uploads/docs/' . $newname;
$docs[] = $_SERVER['DOCUMENT_ROOT'] . '/components/com_fleet/uploads/docs/' . $newname;
} else {
die();
}
}
It uploads an image fine, but since a few days a get a Warning: move_uploaded_file(): Unable to move error. Ive seen these a dozen of times while learning to program, so I did all the usual stuff, check paths, the $_FILES[$file]["error"] and check all the right CHMODs. All is fine, path is spot-on, chmod is too, no errors etc...
1 extra weird thing I noticed the file does get written to the right /docs map but its Filesize is empty, and move_upload_file still sends false...
What am I forgetting? CHOWN maybe? And how can I solve that, I dont have SSH access or something.
Graa after an hour I now found out what was wrong, server Disk Quota was exceeded. Maybe people can still benefit from my problems...

Why do I keep getting "directory does not exist?"

I cannot figure out what I am doing wrong here. The permissions for the directory I have for the file being created have write permissions all across the board. I keep getting "directory does not exist" Thanks for the help!
<?
//creates variables and calls the information from the server
$Name = $_POST['name'];
$desc = $_POST['desc'];
$website =$_POST['web'];
$email =$_POST['email'];
$cname =$_POST['cname'];
echo "your registered name is: ". $Name . ".<br/>";
echo "your registered description is: " . $desc . ".<br/>";
echo "your website address is: " . $website . ".<br/>";
echo "your Confirmation email has been sent to: " . $email . ".<br/>";
echo "your information has been stored, thank you! ";
$cname = trim($cname);
$filename = "data/clubinfo/$cname.txt";
$fp = fopen($filename,'a');
fwrite($fp,$Name);
fwrite($fp,"\n");
fwrite($fp,$email);
fwrite($fp,"\n");
fwrite($fp,$desc);
fwrite($fp,"\n");
fwrite($fp, $website);
fwrite($fp, "\n");
fwrite($fp,"__");
fwrite($fp, "\n");
fclose($fp);
?>
Most likely the script is assuming a different working directory to what you're presuming since you're using a relative path.
You'd be better off specifying the path absolutely or at least in relation to $_SERVER['DOCUMENT_ROOT'] even if you do:
$filename = $_SERVER['DOCUMENT_ROOT'] . "../data/clubinfo/$cname.txt";
The advantage of that is that it's outside your document root so it won't be served directly by your Web server. It will also work no matter the location of your script and will work no matter under what directory you install your Webapp, which can be an issue with dev vs prod deployments.
The data/clubinfo folder does not exist in the current directory.
You need to create it first. (By hand or in PHP)
Alternatively, the current directory might not be what you think it is.
Try using file_put_contents() like this:
file_put_contents("data/clubinfo/$cname.txt", implode("\n", $_POST));
If you want to this value by value you should also use the FILE_APPEND flag.
looks like you have not given the path off the root and the server is looking from the current location. try giving the path off the root.

Categories