Fine Uploader need to chunk a file and rejoin back - php

I am trying to integrate fine uploader [ Jquery wrapper ] for my PHP project. In that, i am trying to upload a 25MB file by using chunking option.
But what is happening here is, It chunks file and stores as blob0, blob1, blob2...
I want to my original file to be stored in the location. But here, the chunks get stored with a different name. What i have tired so far is,
<div id="jquery-wrapped-fine-uploader"></div>
<script src="jquery.js" type="text/javascript"></script>
<script src="jquery.fineuploader-3.5.0.js"></script>
<script>
$(document).ready(function () {
$('#jquery-wrapped-fine-uploader').fineUploader({
debug: true,
request: {
endpoint: 'upload.php',
},
chunking: {
enabled: true,
partSize: 2000000,
paramNames: {
partIndex: 'qqpartindex',
partByteOffset: 'qqpartbyteoffset',
chunkSize: 'qqchunksize',
totalFileSize: 'qqtotalfilesize',
totalParts: 'qqtotalparts',
filename: 'qqfile'
}
}
});
});
</script>
PHP
if ($_FILES["qqfile"]["error"] > 0)
{
echo "Return Code: " . $_FILES["qqfile"]["error"] . "<br>";
} else {
$partIndex = $_POST["qqpartindex"];
$fileName = $_POST["qqfile"];
move_uploaded_file($_FILES["qqfile"]["tmp_name"], "data/" . $_FILES["qqfile"]["name"].$partIndex);
$result['success'] = true;
echo json_encode($result);
}
I don't know where i went wrong and what i have missed. Please someone guide me.

The point is, this is a feature of the fine uploader. The chunks are given as separate files so that in case your upload gets corrupted, you would have a way to compare and discard chunks that are invalid. If you wish to just get the file, what you need is the following:
if ($_FILES["qqfile"]["error"] > 0)
{
echo "Return Code: " . $_FILES["qqfile"]["error"] . "<br>";
} else {
$partIndex = $_POST["qqpartindex"];
$fileName = $_POST["qqfile"];
move_uploaded_file($_FILES["qqfile"]["tmp_name"], "data/" . $_FILES["qqfile"]["name"].$partIndex);
// INSERT CODE HERE TO CHECK THE INTEGRITY OF "data/" . $_FILES["qqfile"]["name"].$partIndex
$file = fopen($filename, 'a');
$content = file_get_contents("data/" . $_FILES["qqfile"]["name"].$partIndex);
if (fwrite($file, $content)) $result['success'] = true;
fclose($file);
echo json_encode($result);
}
, where $filename is the name of the file you are uploading. I would tell you how to get it through this code, but it's probably easier to define it upstream. Also, depending on your upstream code, it will probably be more memory-efficient to do the fopen at the beginning of the upload, and fclose at the end of your code (e.g.
$file = FALSE;
if ($partIndex == 0) $file = fopen("filename");
instead of the line $file = fopen($filename, 'a'); But, in this case you need to fclose($file); only at the end of the upload (or not at all, it will be fclosed once the page loads). But once again, without seeing the rest of your code I cannot know what will work best in this particular case.

Related

Upload fails "move uploaded file"

First off, the upload folder is given 777, and my old upload script works, so the server accepts files. How ever this is a new destination.
I use krajee bootstrap upload to send the files. And I receive a Jason response. The error seems to be around move uploaded file. I bet it's a simple error from my side, but I can't see it.
<?php
if (empty($_FILES['filer42'])) {
echo json_encode(['error'=>'No files found for upload.']);
// or you can throw an exception
return; // terminate
}
// get the files posted
$images = $_FILES['filer42'];
// a flag to see if everything is ok
$success = null;
// file paths to store
$paths= [];
// get file names
$filenames = $images['name'];
// loop and process files
for($i=0; $i < count($filenames); $i++){
$ext = explode('.', basename($filenames[$i]));
$target = "uploads" . DIRECTORY_SEPARATOR . md5(uniqid()) . "." . array_pop($ext);
if(move_uploaded_file($_FILES["filer42"]["tmp_name"][$i], $target)) {
$success = true;
$paths[] = $target;
} else {
$success = false;
break;
}
}
// check and process based on successful status
if ($success === true) {.
$output = [];
$output = ['uploaded' => $paths];
} elseif ($success === false) {
$output = ['error'=>'Error while uploading images. Contact the system administrator'];
// delete any uploaded files
foreach ($paths as $file) {
unlink($file);
}
} else {
$output = ['error'=>'No files were processed.'];
}
// return a json encoded response for plugin to process successfully
echo json_encode($output);
?>
I think field name is the issue. Because you are getting image name with filer42 and upload time, you are using pictures.
Please change
$_FILES["pictures"]["tmp_name"][$i]
to
$_FILES["filer42"]["tmp_name"][$i]
And check now, Hope it will work. Let me know if you still get issue.
The error is not in this script but in the post.
I was using <input id="filer42" name="filer42" type="file">
but it have to be <input id="filer42" name="filer42[]" type="file" multiple>
as the script seems to need an arrey.
It works just fine now.

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.

PHP download file from server from POST

What began here: PHP finding file where post INCLUDES portion of filename
I am trying to finish with this question.
Basically, now that I am able to post a variable to a PHP process, then use that process to find a file in a directory, I now need to be able to download the file if it exists.
Quick recap, after the user has entered a voyage number and the datatable has returned a list of voyages, the user then clicks the link, which is where I'll begin the code:
$('.voyageFileCall').on('click', function()
{
var voyage = $(this).attr('data-voyage');
$.post('fileDownload.php', {voyage:voyage}, function(data)
{
// here is where I need to where either display the file doesn't exist
// or the file downloads
});
});
The process 'fileDownload.php' looks like this:
<?php
if($_POST['voyage'] == true)
{
$voyage = $_POST['voyage'];
$files = scandir("backup/");
if(count($files) > 0)
{
$fileFound = false;
foreach($files as $file)
{
if((preg_match("/\b$voyage\b/", $file) === 1))
{
// I'm guessing the download process should happen here
echo "File found: $file \n"; // <-- this is what I currently have
$fileFound = true;
}
}
if(!$fileFound) die("File $voyage doesn't exist");
}
else
{
echo "No files in backup folder";
}
}
?>
I tried to use the answer found here: Download files from server php
But I'm not exactly sure where I should put the headers, or if I need to use them at all.
The quick solution which i can suggest you is: return path to file if it is exist, and return false if file doesn't exist.
After that in your JS code you can check, if your "data" == false, you can throw an error "file doesn't exist", and if it is not "false", you can call document.location.href = data; - it will redirect your browser to the file and it will be downloaded
Why don't you simply use download attribute:
<?php
if($_POST['voyage'] == true)
{
$voyage = $_POST['voyage'];
$files = scandir("backup/");
if(count($files) > 0)
{
$fileFound = false;
foreach($files as $file)
{
if((preg_match("/\b$voyage\b/", $file) === 1))
{
// I'm guessing the download process should happen here
echo 'File found: <a href="' . $file . '" download>' . $file . '</a> \n'; // <-- this is what I currently have
$fileFound = true;
}
}
if(!$fileFound) die("File $voyage doesn't exist");
}
else
{
echo "No files in backup folder";
}
}
?>
If you really want to use JavasScript to start download then use style="display:none;" for <a> and then in JS just click it:
echo 'File found: <a id="myDownload" style="display:none;" href="' . $file . '" download>' . $file . '</a> \n';
and call it:
$('.voyageFileCall').on('click', function()
{
var voyage = $(this).attr('data-voyage');
$.post('fileDownload.php', {voyage:voyage}, function(data)
{
if(document.getElementById("myDownload")){
document.getElementById("myDownload").click();
}else{
console.log("file does not exist");
}
});
});

bootstrap fileinput, show uploaded files and delete them

how can i show and delete previously uploaded files with the great bootstrap-fileinput plugin from krajee, my code is:
html:
<script>
$("#images").fileinput({
uploadAsync: true,
uploadUrl: "upload.php"
}).on("filebatchselected", function(event, files) {
$("#images").fileinput("upload");
});
</script>
upload.php:
<?php
if (empty($_FILES['images'])) {
echo json_encode(['error'=>'No files found for upload.']);
return;
}
$images = $_FILES['images'];
$success = null;
$paths= [];
$filenames = $images['name'];
for($i=0; $i < count($filenames); $i++){
$ext = explode('.', basename($filenames[$i]));
$target = "uploads" . DIRECTORY_SEPARATOR . basename($filenames[$i]);
if(move_uploaded_file($images['tmp_name'][$i], $target)) {
$success = true;
$paths[] = $target;
} else {
$success = false;
break;
}
}
if ($success === true) {
$output = ['uploaded' => $paths];
} elseif ($success === false) {
$output = ['error'=>'Error while uploading images. Contact the system administrator'];
foreach ($paths as $file) {
unlink($file);
}
} else {
$output = ['error'=>'No files were processed.'];
}
echo json_encode($output);
?>
Has anyone an idea ? i think i have to scan the uploads dir and send it back with json or use $output, but i dont know how to this ?
Since you are using json to upload files, you can use it to delete them too. Make another ajax call to the server by sending an array of the image URLs that you want to remove. Then with PHP you can simply unlink them.
So for example: http://jsfiddle.net/fdzsLa0k/1/
var paths = []; // A place to store all the URLs
// Loop through all images
// You can do it for a single image by using an id selector and skipping the looping part
$('.uploaded-img').each(function(i, v) {
paths.push(this.src); // Save found image paths
})
console.log(paths); // Preview the selection in console
// Send the URLs to the server for deletion
$.ajax({
method: 'post',
data: { images: paths },
url: 'ajax.php' // Replace with your ajax-processing file
}).success(function(response) {
console.log(response); // Do fun stuff: notify user, remove images from the loaded HTML
});
uuuhh, the fileinput script need php version higher than 5.3.3, because the plesk panel of my hosting provider supports only 5.3.3 i have the problems, since 11.5 plesk supports multiple php version for each domain on the server, now with php 5.6 everything works great !

PHP upload image via AJAX/HTML 5 rename file

I am not real good at reading the code for uploading images via php/ajax so i am hoping a php guru can help me out. I am trying to take the image file name and if it has spaces in it then replace those spaces with an underscore "_"
The php code for uploading is this:
$file_name = ( isset($_REQUEST['ax-file-name']) && !empty($_REQUEST['ax-file-name']) )?$_REQUEST['ax-file-name']:'';
$currByte = isset($_REQUEST['ax-start-byte'])?$_REQUEST['ax-start-byte']:0;
if($is_ajax)//Ajax Upload, FormData Upload and FF3.6 php:/input upload
{
//we get the path only for the first chunk
$full_path = ($currByte==0) ? checkFileExits($file_name, $upload_path):$upload_path.$file_name;
//Just optional, avoid to write on exisiting file, but in theory filename should be unique from the checkFileExits function
$flag = ($currByte==0) ? 0:FILE_APPEND;
//formData post files just normal upload in $_FILES, older ajax upload post it in input
$post_bytes = isset($_FILES['Filedata'])? file_get_contents($_FILES['Filedata']['tmp_name']):file_get_contents('php://input');
//some rare times (on very very fast connection), file_put_contents will be unable to write on the file, so we try until it writes
while(#file_put_contents($full_path, $post_bytes, $flag) === false)
{
usleep(50);
}
//delete the temporany chunk
if(isset($_FILES['Filedata']))
{
#unlink($_FILES['Filedata']['tmp_name']);
}
//if it is not the last chunk just return success chunk upload
if($isLast!='true')
{
echo json_encode(array('name'=>basename($full_path), 'size'=>$full_size, 'status'=>1, 'info'=>'Chunk uploaded'));
}
}
else //Normal html and flash upload
{
$isLast = 'true';//we cannot upload by chunks here so assume it is the last single chunk
$full_path = checkFileExits($file_name, $upload_path);
$result = move_uploaded_file(str_replace(" ", "_",$_FILES['Filedata']['tmp_name']), $full_path);//make the upload
if(!$result) //if any error return the error
{
echo json_encode( array('name'=>basename($full_path), 'size'=>$full_size, 'status'=>-1, 'info'=>'File move error') );
return false;
}
}
I've already tried the following (with str_replace(" ", "_", $nameoffile):
$post_bytes = isset($_FILES['Filedata'])? file_get_contents(str_replace(" ", "_",$_FILES['Filedata']['tmp_name'])):file_get_contents('php://input');
That seems to do nothing to rename it. So where am i missing it at?
The problem in your code is , you are trying to rename the temporary name of image file not the actual name
move_uploaded_file(str_replace(" ", "_",$_FILES['Filedata']['tmp_name']), $full_path);//make the upload
So you have to remove the str_replace from temporary name and append this to actual name like this.
move_uploaded_file($_FILES['Filedata']['tmp_name'], str_replace(" ", "_",$full_path));//make the upload
Hope it clarifies your doubt.

Categories