Get the last chunk of upload file - php

So basically https://github.com/blueimp/jQuery-File-Upload/wiki as the uploader and I am using its chunk feature moving on in the server side. I am having a problem in getting the last chunk of the uploaded file.
What I am trying to do is save only to db once the chunks reaches the last the chunk or if the uploader finishes uploading the chunks
ex. chunk size = 10mb
if( isset($_SERVER['HTTP_CONTENT_RANGE']) )
{
$content_range = preg_split('/[^0-9]+/', $_SERVER['HTTP_CONTENT_RANGE']);
// if file is greater or equal to 10mb
if( $content_range[2] + 1 == $content_range[3] )
{
insert data to database here
}
// if file does not need to be chunked file is less than chunk size
else
{
also insert the data to database
}
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$is_chunked_upload = !empty($_SERVER['HTTP_CONTENT_RANGE']);
if ($is_chunked_upload) {
$is_last_chunk = false;
// [HTTP_CONTENT_RANGE] => bytes 10000000-17679248/17679249 - last chunk looks like this
if (preg_match('|(\d+)/(\d+)|', $_SERVER['HTTP_CONTENT_RANGE'], $range)) {
if ($range[1] == $range[2] - 1) {
$is_last_chunk = true;
}
}
}
}

Related

uploaded file is too big php

Hi i have the following code that uploads videos to a server and updates the database accordingly. This code works fine when i run it with a bunch of images and or small video's. See the code below:
for ($i=0; $i<count($_FILES['images']['error']); $i++) {
if ($_FILES['images']['error'][$i] == UPLOAD_ERR_OK) {
$tmpName = $_FILES['images']['tmp_name'][$i];
$name = $_FILES['images']['name'][$i];
$type = $_FILES['images']['type'][$i];
if (strpos($type, 'image') !== false) {
$type = "img";
}elseif(strpos($type, 'video') !== false){
$type = "vid";
}else{
exit();
}
move_uploaded_file(($tmpName), $dir.$name);
$upload = array(
'name'=>$name,
'type'=>$type
);
$uploads[] = $upload;
}
}
But when my client tries to upload a video bigger than 64mb the program doesnt upload it... I already tried to change the max_file_size and other according parameters to allow bigger files. But my clients hosting provider doesnt allow this.
So are there any other ways of uploading big files to my server via my custom cms?
Thomas
So as said in comments. Reference material is below code examples. Trick is to cut the file into chunks that are less than the upload limit. This method can be extended to the point that when a file upload is interrupted you can continu on the last known part. :-)
Basic JavaScript class to assist in uploading the file, determines the chunks to be sent to a PHP server.
function fileUploader() {
// Called when the file is selected
this.onFileSelected = function() {
// Read file input (input type="file")
this.file = this.fileInput.files[0];
this.file_size = this.file.size;
this.chunk_size = (1024 * 1000);
this.range_start = 0;
this.range_end = this.chunk_size;
this.slice_method = 'slice';
this.request = new XMLHttpRequest();
// Start uploading
this.upload();
};
this.upload = function()
{
var self = this,
chunk;
// Last part reached
if (this.range_end > this.file_size) {
this.range_end = this.file_size;
}
// Chunk the file using the slice method
chunk = this.file[this.slice_method](this.range_start, this.range_end);
// Open a XMLHttpRequest
var endpoint = "/url/to/php/server/for/processing";
this.request.open('PUT', (endpoint));
this.request.overrideMimeType('application/octet-stream');
this.request.send(chunk);
// Make sure we do it synchronously to prevent data corruption
this.request.onreadystatechange = function()
{
if (self.request.readyState == XMLHttpRequest.DONE && self.request.status == 200) {
self.onChunkComplete();
}
}
};
this.onChunkComplete = function()
{
if (this.range_end === this.file_size)
{
// We are done, stop uploading
return;
}
this.range_start = this.range_end;
this.range_end = this.range_start + this.chunk_size;
this.upload();
};
}
And for the PHP bit:
...
$out = fopen("{$filePath}.partial", "a+");
fwrite($out, file_get_contents("php://input"));
fclose($out);
...
Big warning here, make sure to properly validate and take security measures to ensure the safety of your clients upload function. You are writing the raw PHP input to a file.
When the upload is done you can rename the file to it's original name including the correct extension.
Reference material:
http://creativejs.com/tutorials/advanced-uploading-techniques-part-1/index.html
https://secure.php.net/manual/en/wrappers.php.php
In a nutshell.. it's break the file into small chunks using a processor, upload the files using conventional methods (like you would normally upload a file), append the input to a temporarily file. Some pitfalls I encountered were sending extra params and alike to the endpoint, avoid those as it's appended to the file and it will corrupt your file.

javascript php upload images request entity too large

I have php javascript images upload problem. When I upload about 20kb, it is OK.
But when I upload over 500kb, it fails and displays the error shown below. My web site is hosted on godaddy. In my local development computer it works and runs smoothly. Do you have any ideas??
I have tried:
ini_set('post_max_size',52428800); // 50 MB
ini_set('upload_max_filesize',52428800) // 50 MB
But does not work.
//------ERROR on Web Pag----------
Request Entity Too Large
The requested resource /index.php/newPost/ does not allow request data with GET requests, or the amount of data provided in the request exceeds the capacity limit.
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
//------------My code----------------------//
function uploadImages($input, $file)
{
if($input == null || $input == "")
{
return false;
}
$stringVal = $input;
$value = str_replace('data:image/png;base64,', '', $stringVal);
if ($this->check_base64_image($value) == false) {
return false;
}
$actualFile = base64_decode($value);
$img = imagecreatefromstring($actualFile);
$imgSize = getimagesize('data://application/octet-stream;base64,' . base64_encode($actualFile));
if ($img == false) {
return false;
}else
{
/*** maximum filesize allowed in bytes ***/
$max_file_length = 100000;
log_message('debug', 'PRE UPLOADING!!!!!!!!');
if (isset($img)){
log_message('debug', 'UPLOADING!!!!!!!!');
// check the file is less than the maximum file size
if($imgSize['0'] > $max_file_length || $imgSize['1'] > $max_file_length)
{
log_message('debug', 'size!!!!!!!!'.print_r($imgSize));
$messages = "File size exceeds $max_file_size limit";
return false;
}else if (file_exists($file)) {
return false;
}else
{
file_put_contents($file, $actualFile);
return true;
}
}
}
}

How can I check that at-least one file is selected for upload

how can I check that user has selected at-least one file for upload in below code ?
i have tried with in_array, isset, !empty functions but no success
please note that userfile input is array in html
if(!empty($_FILES['userfile']['tmp_name'])){
$upload_dir = strtolower(trim($_POST['name']));
// Create directory if it does not exist
if(!is_dir("../photoes/". $upload_dir ."/")) {
mkdir("../photoes/". $upload_dir ."/");
}
$dirname = "../photoes/".$upload_dir;
for($i=0; $i < count($_FILES['userfile']['tmp_name']);$i++)
{
// check if there is a file in the array
if(!is_uploaded_file($_FILES['userfile']['tmp_name'][$i]))
{
$messages[] = 'No file selected for no. '.$i.'field';
}
/*** check if the file is less then the max php.ini size ***/
if($_FILES['userfile']['size'][$i] > $upload_max)
{
$messages[] = "File size exceeds $upload_max php.ini limit";
}
// check the file is less than the maximum file size
elseif($_FILES['userfile']['size'][$i] > $max_file_size)
{
$messages[] = "File size exceeds $max_file_size limit";
}
else
{
// copy the file to the specified dir
if(#copy($_FILES['userfile']['tmp_name'][$i],$dirname.'/'.$_FILES['userfile']['name'][$i]))
{
/*** give praise and thanks to the php gods ***/
$messages[] = $_FILES['userfile']['name'][$i].' uploaded';
}
}
}
}else{
$messages[] = 'No file selected for upload, Please select atleast one file for upload';
dispform();
}
Here's how I do it its a couple of if's and I use a for loop as I allow multiple file uploads from a single drop down but its the if's that are more important to you
$uploaded = count($_FILES['userfile']['name']);
for ($i=0;$i<$uploaded;$i++) {
if (strlen($_FILES['userfile']['name'][$i])>1) {
// file exists so do something
} else {
//file doesn't exist so do nothing
}
}
You'll note I compare against the name element of the global $_FILES this is because you should never be able to upload a file without a name which also applies for no file uploaded
Don't do it client side thats a dumb place to do validation as the user can simply turn js processing off in the browser or it can be blocked by certain addons etc or intercepted and altered via firebug and various browser search hijacking toolbars etc.
Anything like this should always be done server side!
finally I found the answer, I am giving it here for other users,
I have 5 keys in html input array so array index is up to 4
if(!empty($_FILES['userfile']['tmp_name'][0]) or !empty($_FILES['userfile']['tmp_name'][1]) or !empty($_FILES['userfile']['tmp_name'][2]) or !empty($_FILES['userfile']['tmp_name'][3]) or !empty($_FILES['userfile']['tmp_name'][4])){
//at-least one file is selected so proceed to upload
}else{
//no file selected, notify user
}
There are several methods of doing this with PHP (e.g. Check if specific input file is empty), but with JS it's faster and less expensive on the server. Using jQuery you can do this:
$.fn.checkFileInput = function() {
return ($(this).val()) ? true : false;
}
if ($('input[type="file"]').checkFileInput()) {
alert('yay');
}
else {
alert('gtfo!');
}

Looping inside foreach till first matched element is found

First of all apologies for the vague question title. I couldn't come up with a title that made sense.
I'm looping through image files in a directory using:
$folder = 'frames/*';
foreach(glob($folder) as $file)
{
}
The Requirement
I want to measure each file's size and if it's size is less then 8kb, move to the next file and check it's size and do so until you get the file whose size is greater than 8kb. Right now I'm using
$size = filesize($file);
if($size<8192) // less than 8kb file
{
// this is where I need to keep moving until I find the first file that is greater than 8kb
// then perform some actions with that file
}
// continue looping again to find another instance of file less than 8kb
I had a look at next() and current() but couldn't come up with a solution that I was looking for.
So for a result like this:
File 1=> 12kb
File 2=> 15kb
File 3=> 7kb // <-- Found a less than 8kb file, check next one
File 4=> 7kb // <-- Again a less than 8kb, check next one
File 5=> 7kb // <-- Damn! a less than 8kb again..move to next
File 6=> 13kb // <-- Aha! capture this file
File 7=> 12kb
File 8=> 14kb
File 9=> 7kb
File 10=> 7kb
File 11=> 17kb // <-- capture this file again
.
.
and so on
UPDATE
The complete code that I'm using
$folder = 'frames/*';
$prev = false;
foreach(glob($folder) as $file)
{
$size = filesize($file);
if($size<=8192)
{
$prev = true;
}
if($size=>8192 && $prev == true)
{
$prev = false;
echo $file.'<br />'; // wrong files being printed out
}
}
What you need to do is keep a variable indicating if the previous analyzed file was a small one or a big one and react accordingly.
Something like this :
$folder = 'frames/*';
$prevSmall = false; // use this to check if previous file was small
foreach(glob($folder) as $file)
{
$size = filesize($file);
if ($size <= 8192) {
$prevSmall = true; // remember that this one was small
}
// if file is big enough AND previous was a small one we do something
if($size>8192 && true == $prevSmall)
{
$prevSmall = false; // we handle a big one, we reset the variable
// Do something with this file
}
}

Set File Size Limit Message

I wonder whether someone could help me please.
I have to admit I'm relatively new to writing PHP so please bear with me.
Through articles I've read on the internet and some first class tutition from one #Marcio on this site, I've put together a script that allows users to save Image Files to a mySQL database.
I've now gone a little further by restricting the size of the file that can be uploaded, but I I'd like to add a warning message that tells why the file cannot be uploaded i.e. because it's size is greater than the limit set.
I've made an attempt at this, as seen in the code below. But unfortunately I receive an error message stating that there is an unexpected '>' which I know relates to the line I've added, but not sure how to code this another way.
Revised Cut Down Code
<?php
// This function makes usage of
// $_GET, $_POST, etc... variables
// completly safe in SQL queries
function sql_safe($s)
{
if (get_magic_quotes_gpc())
$s = stripslashes($s);
return mysql_real_escape_string($s);
}
// If user pressed submit in one of the forms
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
if (!isset($_POST["action"]))
{
// cleaning title field
$title = trim(sql_safe($_POST['title']));
if ($title == '') // if title is not set
$title = '(No title provided';// use (empty title) string
if (isset($_FILES['photo']))
{
#list(, , $imtype, ) = getimagesize($_FILES['photo']['tmp_name']);
// Get image type.
// We use # to omit errors
if ($imtype == 3) // cheking image type
$ext="png"; // to use it later in HTTP headers
elseif ($imtype == 2)
$ext="jpeg";
elseif ($imtype == 1)
$ext="gif";
else
$msg = 'Error: unknown file format';
if($_FILES["fileupload"]["size"]/1024000 >= 10) // 10mb
{
$fileErrMsg = "<br />Your uploaded file size:<strong>[ ". $_FILES["fileupload"]["size"]/1024000 . " MB]</strong> is more than allowed 10MB Size.<br />";
}
if (!isset($msg)) // If there was no error
{
$data = file_get_contents($_FILES['photo']['tmp_name']);
$data = mysql_real_escape_string($data);
// Preparing data to be used in MySQL query
mysql_query("INSERT INTO {$table}
SET ext='$ext', title='$title',
data='$data'");
$msg = 'Success: Image Uploaded';
}
}
I just wondered whether someone could perhaps take a look at this and let me know what I'm doing wrong.
Many thanks and kind regards
You can use this
if($_FILES["fileupload"]["size"]/1024000 >= 10) // 10mb
{
$fileErrMsg = "<br />Your uploaded file size:<strong>[ ". $_FILES["fileupload"]["size"]/1024000 . " MB]</strong> is more than allowed 10MB Size.<br />";
}
getfilesize() returns image dimensions in pixels, not file size. You need something along the lines of this:
if (filesize($_FILES['tmp_name']) >= 100000)

Categories