So I have this function in javascript to send parts of file to server:
function ajaxPartUpload(url, packageNo, file, attachmentId)
{
var packageMaxSize = 10240; //1048576; //10485760; //reduced for tests
var packageCount = Math.ceil(file.size / packageMaxSize);
var start = packageNo * packageMaxSize;
var stop = (packageNo+1) * packageMaxSize - 1;
if ((packageNo+1) === packageCount || packageCount === 0) {
stop = file.size - 1;
}
var blob = file.slice(start, stop);
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState === FileReader.DONE) {
var data = {
blob: reader.result,
partNo: packageNo,
lastPartNo: packageCount,
fileName: file.name,
fileType: file.type,
fileSize: file.size,
attachmentId: attachmentId,
multipart: true
};
$.ajax({
url: url,
type: 'post',
dataType: 'json',
data: data,
success: function(response) {
if (response.continue === false) {
return true;
} else {
ajaxPartUpload(url, packageNo+1, file, response.attachmentId);
}
}
});
}
};
reader.readAsBinaryString(blob);
}
And It's working as expected, I get in post the binary data of files I'm sending. Under specified url I have script that basicly do this:
$attachment = V()->Attachment->find($_POST['attachmentId']);
$destination_path = $attachment->getPath();
$filePointer = fopen($destination_path, 'a');
$written = fwrite($filePointer, $_POST['blob']);
if ($written == false )
{
throw new Exception('File data not written');
}
fclose($filePointer);
And as long as I have text files it's ok, but when I try to send binary file, the files I'm reciving are about 50% bigger in size, and corrupted, it doesn't matter if I make chunk size big enough to hold all file in one http request or not. What I'm doing wrong?
I have dumped length of 'blob' in javascript right before send and length of recived blob in php: I've got 2 compleatly diffrent results for one chunk max 1 MB file has '28KB' (got from ls -lash):
javascript: 25755
php: 36495
What happend? When I've tired text file all was ok.
@EDIT: Solution in JS change:
blob: reader.result,
to
blob: window.btoa(reader.result),
AND in PHP
$written = fwrite($filePointer, $_POST['blob']);
to
$written = fwrite($filePointer, base64_decode($_POST['blob']));
that solves the problem.
I've added atob in javascript on my result from reader, and then decoded data before reading with base64_decode. It solves the problem.
The problem is that PHP interprets this binary data in some other way, as string perhaps, I don't really know. Anyway sending a 'bit' bigger encoded data saves a lot of nerves.