Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Large file uploads using FileReader and php

I am currently developing an upload module for very large files (larger than the server will ever allow) with progress and all that stuff. See the code bellow. It works for text files, images, even doc and pdf files. It crashes for any other file type. Anyone has any suggestions?

var fr = new FileReader;
chunkSize = 524288;
//chunkSize = window.maxPost;
var chunks = Math.ceil(file.size / chunkSize);
var chunk = 0;
function SendSlice() {
    var start, end;
    start = chunk * chunkSize;
    if (start > file.size) {
        start = end + 1;
    }
    end = start + (chunkSize - 1) >= file.size ? file.size : start + (chunkSize - 1);
    status = chunk == 0 ? "start" : (chunk == chunks ? "end" : "progress");
    if (status == 'start') {
            $("#upload-area").append("<p>Upload started for file " + file.name + "</p>");
    }
    fr.onload = function(e) {
        var sliceData = e.target.result;
        $.ajax({
            type : "POST",
        url : "uploader.php",
        data : {
            filename : file.name,
            status : status,
            slice : sliceData
        }
        }).success(function(data) {
            if (++chunk <= chunks) {
                SendSlice();
                var progress = (chunk / chunks) * 100;
                $("#progress-text").html(progress.toFixed(2) + "%");
                $("#progress").css({
                    width : progress + "%"
                });
            } else {
                $("#upload-area").append("<p>File " + file.name + " uploaded succesfully. Download file <a target='_blank' href='uploads/" + file.name + "'>here</a></p>");
            }
        });
    };
    fr.readAsDataURL(file.slice(start, end));
}
SendSlice();

And the php code:

 if($_POST['status'] == 'start') {
if (file_exists("uploads/" . $_POST['filename'])) {
    unlink("uploads/" . $_POST['filename']);
}
 }
 $data = explode(",", $_POST['slice']);
 $data = $data[1];
 $data = base64_decode($data);
 file_put_contents("uploads/" . $_POST['filename'], $data, FILE_APPEND);

Also, i have tried using readAsBinaryString, but i have not idea how the handle the result in PHP. Please advice

like image 937
d4rkpr1nc3 Avatar asked Jan 30 '26 01:01

d4rkpr1nc3


1 Answers

This is just a shot in the dark, but looking at the file.slice API (http://www.w3.org/TR/FileAPI/#dfn-slice), it says:

"The slice method returns a new Blob object with bytes ranging from the optional start parameter upto but not including the optional end parameter, and with a type attribute that is the value of the optional contentType parameter."

However, you subtract 1 from "end" before using it - does that mean you leave out 1 byte at each chunk (since the end byte isn't included anyway)?

Also, you do sanitize $_POST['filename'] before using it - not that someone puts "../yourscript.php" in there?

like image 129
Aaa Avatar answered Jan 31 '26 14:01

Aaa