I have been working on a browser based file uploader that sends files to our S3 buckets for the past couple of months. I've made great progress in the last couple of weeks. However, my biggest road block came in the form of iDevices. Pretty much anything that runs on iOS 8 has been giving me major headaches relating to my uploader. I am able to run my program on Chrome, Firefox, and Safari on desktops/laptops on both PC and MAC. However, when it comes to mobile devices, only Android devices work the intended way. On iOS, Chrome only uploads small files and anything large will return a file that has a size of 0. Safari out right fails. I know that there have been issues with iOS 8 relating to this issue, but from my research, this issue should have been taken care of already. Anyways, I was wondering if there was a work around this problem so that I can upload my files like I am doing for the other devices and browsers.
Error uploading a small image file:
Syntax: JSON Parse error: Unexpected EOF
Failed to load resource: request body stream exhausted
Error uploading a big video file:
Failed to load resource: request body stream exhausted
SyntaxError: JSON Parse error: Unrecognized token '<'
If you would like to see any examples of my code, feel free to ask as I will edit my post for this request.
upload.js
    var files;                      // Array of inputed files
    var ownerName;                  // Inputed name of file owner
    var totalSize = 0;              // Total file size of all files
    var loaded    = 0;              // Loaded data amount
    var MB        = 1024 * 1024;    // 1 MB
    var partSize  = MB;             // Data amount of part of chunk of file 
    var chunkSize = 5 * MB;         // Data amount of chunk of file
    function request(command, xhr, formdata){
        xhr.open("POST", "FileUploader.php", true);
        if(command === 'UploadPart' || command === 'PutObject')
            xhr.upload.addEventListener("progress", progressHandler, false);
        xhr.addEventListener("load", completeHandler, false);
        xhr.addEventListener("error", errorHandler, false);
        xhr.addEventListener("abort", abortHandler, false);
        xhr.send(formdata);
        return xhr;
    }
    function uploadFile(){
        reset();
        if (window.File && window.FileReader && window.FileList && window.Blob){
            files = _("file").files;
            totalSize = calcTotalSize(files);
            for (var i = 0; i < files.length; i++){
                var key = createKey(_("name").value, files[i]);
                if (files[i].size >= chunkSize)
                    createMultipartUpload(i, key);  
                else
                    putObject(i, key);
            }
        }
        else
            alert("Your browser does not support our File Uploader.");
    }
    function createMultipartUpload(i, key){
        var formdata = new FormData();
        formdata.append("command", 'CreateMultipartUpload');
        formdata.append("fileindex", i);
        formdata.append("key", key);
        var xhr = request('CreateMultipartUpload', new XMLHttpRequest(), formdata);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4)
                uploadPart(JSON.parse(xhr.responseText), 1);
        };
    }
    function uploadPart(sendBackData, partNum){
        console.log("Uploading part " + partNum); 
        var fileIndex = sendBackData['fileindex'];
        var file      = files[fileIndex];
        if (partNum > Math.ceil(file.size / chunkSize)) {
            completeMultipartUpload(sendBackData);
            return;
        }
        var blobs     = [];
        var start     = (partNum - 1) * chunkSize;
        var end       = start + partSize;
        var index     = 0;
        while (start < chunkSize*partNum){
            blobs.push(file.slice(start, end));
            start = end;
            end = start + partSize;
            index++;
        }
        var formdata = new FormData();
        for(var i = 0; i < index; i++)
            formdata.append("file[]", blobs[i]);
        formdata.append("command", 'UploadPart');
        formdata.append("uploadId", sendBackData['uploadId']);
        formdata.append("key", sendBackData['key']);
        formdata.append("partNumber", partNum);
        var xhr = request('UploadPart', new XMLHttpRequest(), formdata);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4)
                uploadPart(sendBackData, partNum + 1);
        };
    }
    function completeMultipartUpload(sendBackData) {
        var formdata = new FormData();
        formdata.append("command", 'CompleteMultipartUpload');
        formdata.append("uploadId", sendBackData['uploadId']);
        formdata.append("key", sendBackData['key']);
        
        var xhr = request('CompleteMultipartUpload', new XMLHttpRequest(), formdata);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                var sendBackData = JSON.parse(xhr.responseText);
                if(sendBackData['success'])
                    displayURL(sendBackData['url']);
            }
        };
    }
FileUploader.php
<?php
    function sendJson($arr)
    {
        header('Content-Type: application/json');
        die(json_encode($arr));
    }
    $s3 = S3Client::factory(array(
        'key'     => AWS_KEY,
        'secret'  => AWS_SECRET_KEY
    ));
    $command = $_POST['command'];
    s3Command($command);
function s3Command($command){
    $key = $_POST['key'];
    switch ($command) {
        case 'CreateMultipartUpload':
            $fileindex = $_POST['fileindex'];
            
            $response = $GLOBALS["s3"]->createMultipartUpload(array(
                'Bucket'    => TMP_IMG,
                'Key'       => $key,
                'ACL'       => 'public-read',
            ));
            $uploadId = $response['UploadId'];
            sendJson(array(
                'uploadId'  => $uploadId,
                'key'       => $key,
                'fileindex' => $fileindex
            ));
            break;
        case 'UploadPart':
            $tmp_files = $_FILES['file'];
            $files = array();
            for ($i = 0; $i < count($tmp_files['name']); $i++){
                $files[] = array(
                    'name' => $tmp_files['name'][$i],
                    'tmp_name' => $tmp_files['tmp_name'][$i],
                    'type' => $tmp_files['type'][$i],
                    'size' => $tmp_files['size'][$i],
                    'error' => $tmp_files['error'][$i]
                );
            }
            
            $body = mergeFiles($files);
            $result = $GLOBALS["s3"]->uploadPart(array(
                'Bucket'    => TMP_IMG,
                'Key'       => $key,
                'UploadId'  => $_POST['uploadId'],
                'PartNumber'=> $_POST['partNumber'],
                'Body'      => $body
            ));
            break;
        case 'CompleteMultipartUpload':
            $partsModel = $GLOBALS["s3"]->listParts(array(
                'Bucket' => TMP_IMG,
                'Key'       => $key,
                'UploadId'  => $_POST['uploadId']
            ));
            $model = $GLOBALS["s3"]->completeMultipartUpload(array(
                'Bucket' => TMP_IMG,
                'Key' => $key,
                'UploadId' => $_POST['uploadId'],
                'Parts' => $partsModel['Parts'],
            ));
            $url = $GLOBALS["s3"]->getObjectUrl(TMP_IMG, $key);
            
            $type = explode('/', $key);
            if($type[0] == 'image'){
                $result = $GLOBALS["s3"]->getObject(array(
                    'Bucket' => TMP_IMG,
                    'Key'    => $key
                ));
                $body = $result['Body'];
                $url = resizeImage($url);
            }
            sendJson(array(
                'success' => true,
                'url'     => $url
            ));
            break;
        case 'AbortMultipartUpload':
            $s3->abortMultipartUpload(array(
                'Bucket'   => TMP_IMG,
                'Key'      => $key,
                'UploadId' => $_POST['uploadId']
            ));
            break;
    }
}
?>