Large file uploads using FileReader, AJAX and PHP - security issues
<p>I am developping a tool which enables the user to upload large files (and by large i mean "size doesn't matter" large). I have pasted bellow the part of the code that actually handles the "upload" in JavaScript. The code itself works great, absolutely no problem. I have uploaded a 500 MB file in aprox. 15 minutes That is, on a crappy computer which also serves as a server. I expect it to work a lot better on an actual server.</p>

<p>What i'm asking for is suggestions for security that won't have to big an impact on performance and, also, performance upgrades. The way i see it, any attempt to encode/pack the data sent to the server will have a BIG impact on the performance.</p>

<p>Another issue is the chunkSize. I let the programmer choose how big a "slice" of file should be. However the limit is the server's max_post_size. By default it is set to 1024 * 512 bytes.</p>

<p>I have noticed(by countless test) that if I increase the chunk size the entire proccess of uploading works faster. The reason is obvious : The progress event and the communication with the server triggers less often. However, in case of a progress bar, the accuracy will be very low and it might cause the user to believe the application has crashed and close the page.</p>

<p>So basically i have these 2 questions :</p>

<p>1: how to encode/pack the data without affecting (too much) the performance</p>

<p>2: How could i increase the overall performance of the tool</p>

<p>Meanwhile, i will do some research myself.</p>

<p>Here is code that handles the upload : </p>

<pre><code>Uploader.UploadFile = function (file, instance) {
    var fr = new FileReader;
    chunkSize = instance.settings.chunkSize &gt; window.maxPost ? window.maxPost : instance.settings.chunkSize;
    var chunks = Math.ceil(file.size / chunkSize);
    var chunk = 0;
    var startTime = (new Date()).getTime();
    function SendSlice() {
        var start, end;
        start = chunk * chunkSize;
        if (start &gt; file.size) {
            start = end + 1;
        }
        end = start + (chunkSize) &gt;= file.size ? file.size : start + (chunkSize);
        status = chunk == 0 ? "start" : (chunk == chunks ? "end" : "progress");
        if (status == 'start') {
            if(instance.settings.onStartUpload &amp;&amp; instance.settings.onStartUpload.call) {
                var event = new Uploader.Event.StartUpload({
                    time : (new Date()).getTime(),
                    file : file,
                    target : instance.element
                });
                instance.settings.onStartUpload(event);
            }
        }
        fr.onload = function(e) {
            var sliceData = e.target.result;
            $.ajax({
                type : "POST",
                url : "uploader.php",
                data : {
                    filename : file.name,
                    path : instance.settings.path,
                    status : status,
                    slice : sliceData
                }
            }).success(function(data) {
                if (++chunk &lt;= chunks) {
                    if(instance.settings.onProgress &amp;&amp; instance.settings.onProgress.call) {
                        var event = new Uploader.Event.Progress({
                            time : (new Date()).getTime(),
                            file : file,
                            target : instance.element,
                            pieces: chunks,
                            currentPiece : chunk,
                            percent : (chunk / chunks) * 100,
                            bytesUploaded : end,
                            bytesRemaining : file.size - end
                        });
                        instance.settings.onProgress(event);
                    }
                    SendSlice();
                } else {
                    if(instance.settings.onCompleteFile &amp;&amp; instance.settings.onCompleteFile.call) {
                        var time = (new Date()).getTime();
                        var duration = time - startTime;
                        var event = new Uploader.Event.FileComplete({
                            time : time,
                            file : file,
                            target : instance.element,
                            duration : duration
                        });
                        instance.settings.onCompleteFile(event);
                    }
                }
            });
        };
        fr.readAsDataURL(file.slice(start, end));
    }
    SendSlice();
}
</code></pre>
