I've setup an Angular based file upload using the ng-file-upload plugin (https://github.com/danialfarid/ng-file-upload) and I've been handling the file upload with a PHP script.
The file upload and script work on smaller files (tested it on < 1MB), but fails on a larger file (9MB). This leads me to believe that there's a file upload issue. However, I've already created a .user.ini file in the /wwwroot folder with a single line:
upload_max_filesize=20M
Is there another reason why the $_FILES and $_POST arrays would be empty?
JS Code:
Upload.upload({
url: '/scripts/receiveFile.php',
file: file
}).then(function(resp) {
console.log(resp.data);
}, function(resp) {
console.log(resp.data);
}, function(evt) {
var progressPercent = parseInt(100.0 * evt.loaded / evt.total);
console.log(progressPercent + "%");
});
HTML Code:
<div>
<h1>Upload</h1>
<input type="file" accept=".zip" ngf-select="submitFile($file)"></input>
</div>
PHP Code:
$file_name = basename($_FILES['file']['name']);
$file_tmp_name = $_FILES['file']['tmp_name'];
The script fails because 'file' is undefined in the $_FILES array - because the $_FILES array is empty.
Thanks!
PHP has a confusing was of doing file uploads. To set a larger upload size, you should set both upload_max_filesize and post_max_size. These can be independently different values, as they do different things.
post_max_size is the maximum file size that can be sent in a POST request to the PHP script. upload_max_filesize is the maximum file size allowed via any method.
Related
I have an upload.php script, that I access from a mobile device, to upload documents to.
Whenever I upload an image of some sort, that is < 1MB, it works perfectly, however, when uploading a file larger than that, it will be corrupted.
The upload script also renames the file, and removes the extension from it, if this could have anything to do with the error...
Here's the script:
<?php header('Access-Control-Allow-Origin: *');
//Read parameters - I use this when I'm adding the file to the database.
$documentuniqueid = addslashes($_REQUEST['documentuniqueid']);
$type = addslashes($_REQUEST['type']);
$notes = addslashes($_REQUEST['notes']);
//Get file name
$filename = urldecode($_FILES["file"]["name"]);
// Check for errors
if($_FILES['file']['error'] > 0){
outputJSON('An error ocurred when uploading.');
}
// Check filetype
//if($_FILES['file']['type'] != 'image/png'){
// outputJSON('Unsupported filetype uploaded.');
//}
// Check filesize
if($_FILES['file']['size'] > 500000){
outputJSON('File uploaded exceeds maximum upload size.');
}
// Check if the file exists
if(file_exists('upload/' . $_FILES['file']['name'])){
outputJSON('File with that name already exists.');
}
// Upload file
if(!move_uploaded_file($_FILES['file']['tmp_name'], 'documents/'.$documentuniqueid)){
outputJSON('Error uploading file - check destination is writeable.');
}
?>
Download script looks like this:
<?php
sleep(2);
$document_id = addslashes($_REQUEST['document_id']);
if($document_id != "") {
$real_document_name = GetRealFileName($document_id);
if($real_document_name != "ERROR") {
$original_filename = "http://www.whatever.com/documents/".$document_id;
$new_filename = $real_document_name;
//Headers
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $original_filename));
header("Content-Length: " . filesize($original_filename));
header('Content-disposition: attachment; filename="'.$new_filename.'"');
//clean up
ob_clean();
flush();
readfile($original_filename);
exit();
}
}
?>
Any tips on improving this?
Or any insight, on why is this not working correctly?
You can see that I am renaming the files upon upload, to a random string, and them when downloading, I look up the filenames and rename it back to the original one.
That works as expected for the small file sizes.
I also have to note, that even if I go in manually into the FTP, download the uploaded file and add the right extension myself, I'm unable to open them. The images look messed up, and PDFs, for instance are corrupted.
PHP DETAILS:
both post_max_size and upload_max_filesize is set to 100M. max_file_uploads is set to 20 and file_uploads is ON
max_input_time : 60
max_execution_time : 3000
Increase the size of upload file property of the php.ini file inside /etc/php5/apache2/.
Set:
upload_max_filesize = 50M
I think you do not have enough space in your host, Try to upload by FTP "FileZilla for example" and check the log messages
also do not forget to check these values
upload_max_filesize
post_max_size
max_input_time
max_execution_time
To keep the original name of file you need to change
move_uploaded_file($_FILES['file']['tmp_name'], 'documents/'.$documentuniqueid)
to
move_uploaded_file -
move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name'])
or write this line in upload script to see the information about the file
$_FILES -
print_r($_FILES);
sorry for my english, i hope i helped.
I can upload the files if they are fitting this validation rule
'user_file' => 'file|max:10240|mimes:xls,xlsx,doc,docx,pdf,zip'
all goes fine.
I have set my upload_max_filesize to 32MB and post_max_size to 40MB in php.ini
but if i try to upload a file bigger than 40MB my validation rules don't even trigger. I get TokenMismatchException error....
If someone can verify this by simply trying to upload some very big file (a video file for example)
When You exceed post payload size - everything is dropped, so csrf_token does not come to laravel and the upload file is empty so it cannot be validated.
UPDATE
To fix this you need to check the file size before the uploading with javascript or jquery
here is an example:
How to check file input size with jQuery?
In the case of file uploads, the file has to be copied to temp location into the server then the rules will work. so your server will not allow files of size greater than 40MB (post_max_size) into the temp location so rules will not work.
Instead, to fix this you need to do frontend validation for files.
You can do this using simple Javascript as shown below,
$('input[type="file"]').change(function () {
if (this.files[0] != undefined) {
var name = this.name;
var filesize = this.files[0].size;
var field = $('#' + this.name).parents('.input-group');
//check if file size is larger than 3MB(which is 3e+6 bytes)
if (filesize > 3000000) {
alert(filesize);
//reset that input field if its file size is more than 3MB
$('[name="' + name + '"]').val('')
}
}
});
you can just include this for all input of type='file' by changing size limit in bytes.
I encountered the same problem. You should as well check that the validator is checking file data, not post data :
I've tested :
$validator = Validator::make($request->post(), [
myfield' => 'required|image|mimes:jpeg,png,jpg,gif|max:1000000'
]);
Should have been :
$validator = Validator::make($request->file(), [
myfield' => 'required|image|mimes:jpeg,png,jpg,gif|max:1000000'
]);
I want to have a small upload limit (e.g. 100 kb for testing, perhaps 6 Mb ultimately). The size of the upload can be checked:
before the upload
fail when too much is uploaded
after the upload
If the user is trying a 1 Gb file ideally (1) should happen so that the file isn't uploaded at all. If not, (2) should happen so that it doesn't take long before the user knows the file is too big. I'd like to avoid the other possibility (3).
In HTML5 but not in IE9 the filesize can be checked before uploading using:
this.files[0].size
Get file size before uploading
In IE9 the following might work if the security settings are adjusted:
var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;
var objFile = objFSO.getFile(filePath);
var fileSize = objFile.size; //size in kb
Ideally I'd like to use a method that works with IE9. I've heard about flash files being used. I'd like a method that is separate - not using a big plugin.
Here is my code. At the moment it uploads the whole file before it checks if the file size is too big.
<?php
if (isset($_FILES['myfile'])) {
if ($_FILES['myfile']['error'] == UPLOAD_ERR_FORM_SIZE) {
// $_FILES['myfile']['size'] is 0
echo 'Error: file is too big!<br>';
}
else if ($_FILES['myfile']['size'] > 100000) {
echo 'File size is too big!<br>';
}
else {
echo 'File uploaded ok.<br>';
}
}
var_dump($_FILES);
?>
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
<input type="file" name="myfile" />
<input type="submit" value="Submit" />
</form>
The small upload limit is just for one form so I don't want to change the global PHP settings file.
I'm not sure using MAX_FILE_SIZE is a good idea - the person still has to upload the entire file and the filesize data is lost (I might want to tell people how big their upload was)
ini_get('post_max_size') returns 8M and ini_get('upload_max_filesize') returns 32M. If files that are over 8 Mb try to be uploaded the file is still fully uploaded (even 40+ Mb). After larger than 8 Mb files are uploaded var_dump($_FILES) returns an empty array.
If the file is bigger than about 600 Mb I get a 413 error... that is (1).
So I want to do (1) or (2) in IE9, PHP and jQuery.
I'm trying to store images on an FTP server to be used on other pages, but I'm getting multiple errors trying to get this work. Running everything on XAMPP. First I use input on an html page:
<input type="file" name="image" required>
Then I bring it over and try to upload it:
$image = $_POST["image"];
$ftpCon = ftp_connect("127.0.0.1", "21") or die("Could not connect to FTP");
ftp_fput($ftpCon, "image.png", $image, FTP_BINARY);
ftp_close($ftpCon);
With this code I get this error: " ftp_fput() expects parameter 3 to be resource, string given"
Change the line
$image = $_POST["image"];
to
$image = $_FILES['image']['tmp_name'];
When you upload items (files) via a form it's populated in the $_FILES superglobal.
An associative array of items uploaded to the current script via the
HTTP POST method.
http://se2.php.net/manual/en/reserved.variables.files.php
Make sure you also set the form with enctype='multipart/form-data'
So the first line of the PHP has to be changed to:
$image = $_FILES['image']['tmp_name'];
The $_FILES is associtaive and contains the following data:
(userfile = image, in your case)
$_FILES['userfile']['name']
The original name of the file on the client machine.
$_FILES['userfile']['type']
The mime type of the file, if the browser provided this information. An example would be "image/gif". This mime type is however not checked on the PHP side and therefore don't take its value for granted.
$_FILES['userfile']['size']
The size, in bytes, of the uploaded file.
$_FILES['userfile']['tmp_name']
The temporary filename of the file in which the uploaded file was stored on the server.
$_FILES['userfile']['error']
The error code associated with this file upload. This element was added in PHP 4.2.0
I have multiple file uploads but the $_FILES seems to be chunked after 20 inputs
var_dump($_FILES); //gives array(20){ ... } although there are more file inputs
This is the public php_info
Which parameter is responsible for this limit ?
As a workaround, I used some javascript:
<input id="input_fileXX" type="file" class="input_file">
----
$('.input_file').on('change',function(){
$(this).prop('name',$(this).prop('id'));
});
This allows to only send the inputs that have change. This is useful when you can't change php.ini.
http://www.php.net/manual/en/features.file-upload.multiple.php
Since PHP 5.2.12, the max_file_uploads configuration setting acts as a limit on the number of files that can be uploaded in one request. You will need to ensure that your form does not try to upload more files in one request than this limit.