jQuery post size limitation using canvas.todataurl() - php

I'm trying to upload a canvas.todataurl() image (getUserMedia) to server using jQuery post and php to handle the data, but I'm having some problems. All the images I'm uploading end up being corrupted, half of the image is missing. I also have a MySQL database where I'm storing data related to the image (title, text, date and the like). It seems that the more I have the related data the more the image get corrupted.
Therefore, I'm wondering is this a browser limitation or does this have something to do with jQuery post. I've also checked the PHP max_post_size and it's 16mb, so that shouldn't be a problem. I don't have access to the server settings. I'm quite puzzled with this, what can I do? Is it possible to divide the canvas.todataurl() to multiple parts and then post?
JavaScript
window.addEventListener('DOMContentLoaded', function() {
var video = document.getElementById('videoStream');
var canvas = document.getElementById('canvasImage');
var status = document.getElementById('status');
var button = document.getElementById('button');
//var others = document.getElementById('others');
var imageHolder;
document.getElementById('form').style.display = 'none';
var image = null; // kuvan datauri joka lähtee php:lle
window.URL || (window.URL = window.webkitURL || window.mozURL || window.msURL);
navigator.getUserMedia || (navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia);
// toString : function() {return "video,audio";} canarya varten
if (navigator.getUserMedia) {
navigator.getUserMedia({video: true, audio: false, toString : function() {return "video,audio";}}, onSuccess, onError);
} else {
status.innerText = "getUserMedia is not supported in your browser, sorry :(";
}
function onSuccess(stream) {
var source;
if (window.webkitURL) {
source = window.webkitURL.createObjectURL(stream);
} else {
source = stream; // Opera ja Firefox
}
video.width = 500;
video.height = 375;
video.autoplay = true;
video.src = source;
}
function onError() {
status.innerText = "Please allow access to your webcam.";
}
button.addEventListener('mousedown', function() {
// Poistetaan aikaisempi kuva jos sellaista on
//document.body.removeChild(imageHolder);
// luodaan kuva uudestaan
imageHolder = document.createElement('figure');
imageHolder.id = 'imageHolder';
document.body.appendChild(imageHolder);
img = document.createElement('img');
imageHolder.appendChild(img);
// kuva on yhtäsuuri kuin video
canvas.width = video.width;
canvas.height = video.height;
img.width = 350;
img.height = 225;
// piirretään canvasille kuva videosta
var context = canvas.getContext('2d');
context.drawImage(video, 0, 0, canvas.width, canvas.height);
}, false);
button.addEventListener('mouseup', function() {
// Canvasilta kuvaksi levylle tallentamista varten
canvas.style.display = 'none';
video.style.display = 'none';
button.style.display = 'none';
others.style.display = 'none';
document.getElementById('form').style.display = 'block';
image = canvas.toDataURL('image/png');
img.src = image;
}, false);
// jquery post
$('#send').click(function(){
var image2 = image.replace('data:image/png;base64,', '');
$.post('upload.php',
{
title: $('#title').val(),
blog: $('#blog').val(),
category: $('#category').val(),
author: $('#author').val(),
imagename: image2
});
});
}, false);
PHP upload.php
define('UPLOAD_DIR', 'images/');
$img = $_POST['imagename'];
$img = str_replace(' ','+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Tiedoston tallennus ei sitten onnistu millään...';
$imagename = $file; // this is the file name for the MySQL database
My problem is (I think) image = canvas.toDataURL('image/png'); and the jQuery post.
The canvas.toDataUrl() string is about 700 000 letters long.

You might wanna try this:
<?php
$decoded = "";
for ($i=0; $i < ceil(strlen($encoded)/256); $i++)
$decoded = $decoded . base64_decode(substr($encoded,$i*256,256));
?>
I got it from here: http://www.php.net/manual/en/function.base64-decode.php#92980
The code basically tries to partially decodes the base64 string. I haven't tested this though. I've never dealt with base64 images as big as what you're working with.

Split it, use two, variables and merge in php, works fine. ;-)
var resourcelength_all = resource.length;
var resourcelength_split = resourcelength_all / 2;
var resource_part1 = resource.substr(0, resourcelength_split);
var resource_part2 = resource.substr(resourcelength_split, resourcelength_all);

Related

Send raw data to PHP via XMLHttpRequest

I am selecting a file and sending it through XMLXttpRequest like this :
var upload_form = $('#upload_form'),
file_input = $('#file_input'),
file_list = $('#file_list'),
submit_btn = $('#submit_btn'),
uploaders = [];
file_input.on('change', onFilesSelected);
upload_form.on('submit', onFormSubmit);
/**
* Loops through the selected files, displays their file name and size
* in the file list, and enables the submit button for uploading.
*/
function onFilesSelected(e) {
var files = e.target.files,
file,
list_item,
uploader;
for (var i = 0; i < files.length; i++) {
file = files[i];
uploader = new ChunkedUploader(file);
uploaders.push(uploader);
list_item = $('<li>' + file.name + '(' + file.size.formatBytes() + ') <button>Pause</button></li>').data('uploader', uploader);
file_list.append(list_item);
}
file_list.show();
submit_btn.attr('disabled', false);
}
so for each file that I add, I create a new ChunkedUploader object, which chunks the file in little 1MB files.
The code for the ChunkedUploader object is as follows:
function ChunkedUploader(file, options) {
if (!this instanceof ChunkedUploader) {
return new ChunkedUploader(file, options);
}
this.file = file;
this.options = $.extend({
url: 'index/upload'
}, options);
this.file_size = this.file.size;
this.chunk_size = (1024 * 100); // 100KB
this.range_start = 0;
this.range_end = this.chunk_size;
if ('mozSlice' in this.file) {
this.slice_method = 'mozSlice';
}
else if ('webkitSlice' in this.file) {
this.slice_method = 'webkitSlice';
}
else {
this.slice_method = 'slice';
}
this.upload_request = new XMLHttpRequest();
this.upload_request.onload = this._onChunkComplete();
}
_upload: function() {
var self = this,
chunk;
// Slight timeout needed here (File read / AJAX readystate conflict?)
setTimeout(function() {
// Prevent range overflow
if (self.range_end > self.file_size) {
self.range_end = self.file_size;
}
chunk = self.file[self.slice_method](self.range_start, self.range_end);
self.upload_request.open('POST', self.options.url, true);
self.upload_request.overrideMimeType('application/octet-stream');
if (self.range_start !== 0) {
self.upload_request.setRequestHeader('Content-Range', 'bytes ' + self.range_start + '-' + self.range_end + '/' + self.file_size);
}
self.upload_request.send(chunk);
}, 200);
},
It all works okay, but on the PHP end I receive nothing through :$_GET,$_POST or $_FILE. I can see in Firebug that raw data is being sent through post, there are some gibberish data being sent, I presume it's the small chunk that I just cropped from the original file. I have looked everywhere and I can't find anything releated to this case.
Can you point out what I am doing wrong, because I have to no clue.
You may want to file_get_contents('php://input') instead: this is the raw request body, whereas $_POST is already a parsed representation.
See http://php.net/manual/en/wrappers.php.php#wrappers.php.input

jquery ajax upload file with post

hi guys i need your help im not very good with ajax im trying to upload a image using a form with php the image is not getting to the php i got error on
Notice: Undefined index: ImageFile in line 9
the line is this one
move_uploaded_file($_FILES['ImageFile']['tmp_name'], "$Destination/$NewImageName");
this is my jquery
$("#send_friend").click(function(e) {
e.preventDefault();
$("#message").empty();
$('#loading').show();
// getting the values that user typed
var add_friends = '1';
var friend_name = $("#friend_name").val();
var friend_url = $("#friend_url").val();
var ImageFile = $('#ImageFile').prop('files')[0];
// forming the queryString
var data=
'add_friends=' + add_friends +
'&clan_name=' + clan_name +
'&friend_name=' + friend_name +
'&friend_url=' + friend_url +
'&ImageFile=' + ImageFile;
// ajax call
$.ajax({
type: "POST",
url: "components/friends.php",
data: data,
success: function(data){ // this happen after we get result
$('#loading').hide();
$("#message").html(data);
}
});
return false;
});
this is my php
if(isset($_POST['add_friends'])){
include "../_database/database.php";
$Destination = '../imagenes/friends';
$friend_name = $database ->real_escape_string(htmlentities($_REQUEST['friend_name']));
$friend_url = $database ->real_escape_string(htmlentities($_REQUEST['friend_url']));
if(!isset($_FILES["ImageFile"]) || !is_uploaded_file($_FILES["ImageFile"]["tmp_name"])){
$NewImageName= 'default.png';
move_uploaded_file($_FILES["ImageFile"]["tmp_name"], "$Destination/$NewImageName");
}
else{
$RandomNum = rand(0, 999);
$ImageName = str_replace(' ','-',strtolower($_FILES['ImageFile']['name']));
$ImageType = $_FILES["ImageFile"]["type"];
$ImageExt = substr($ImageName, strrpos($ImageName, '.'));
$ImageExt = str_replace('.','',$ImageExt);
$ImageName = preg_replace("/\.[^.\s]{3,4}$/", "", $ImageName);
$NewImageName = $ImageName.'-'.$RandomNum.'.'.$ImageExt;
move_uploaded_file($_FILES["ImageFile"]["tmp_name"], "$Destination/$NewImageName");
}
$sql = "INSERT INTO family (name,url, shield)
VALUES ('".$friend_name."', '".$friend_url."', '".$NewImageName."')";
$r1 = mysqli_query($database,$sql);
$sqlResult = $r1;
/*** run the sql statement ***/
}
and my html
<div class="form-group">
<label for="exampleInputFile" class="supercell">Shield</label>
<input type="file" id="ImageFile" name="ImageFile"/>
only with the file i have some problems the database is been populated with all the other vars but can´t get the file to pass to the php any help will be really appreciated
You need to set the contentType to multipart/form-data because the form includes a file.
type: "post",
contentType: "multipart/form-data"

$_SERVER["HTTP_REFERER"]; is null on firefox when accessed vai `swf` movie

I'm trying to upload file using flash So
I've following code in action-script:
var fileRef:FileReferenceList = new FileReferenceList();
fileRef = new FileReferenceList();
fileRef.browse(new Array( new FileFilter( "Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png" )));
fileRef.addEventListener(Event.SELECT, fileSelectHandler);
var uploadURL:URLRequest = new URLRequest();
var uploadPhotoScript:String = "http://localhost/uploader/upload.php";
uploadURL.url = uploadPhotoScript;
function fileSelectHandler(event:Event):void {
for each(var fileToUpload:FileReference in fileRef.fileList){
uploadSingleFile(fileToUpload);
}
}
function uploadSingleFile(file:FileReference):void {
file.addEventListener(ProgressEvent.PROGRESS, onUploadProgress);
file.upload(uploadURL);
file.addEventListener(Event.COMPLETE, completeHandler);
}
function onUploadProgress(e:ProgressEvent):void
{
var f:FileReference = e.currentTarget as FileReference;
var fileName:String = f.name; //Now I know which file it is, I can update accordingly
var progress:Number = (e.bytesLoaded / e.bytesTotal) * 100; //shows percent, you might want to round this off using Math.round(number);
}
function completeHandler(event:Event):void {
trace("upload complete");
}
upload.php:
<?php
if(isset($_SERVER["HTTP_REFERER"]){
$ref=$_SERVER["HTTP_REFERER"];
$ref=explode($ref,"/");
$ref=$ref[2];
if($ref=="localhost"){
if(!empty($_FILES)){
$tmpfile = $_FILES['Filedata']['tmp_name'];
$targetfile = dirname(__FILE__) . '/' . $_FILES['Filedata']['name'];
move_uploaded_file($tmpfile, $targetfile);
}
}
else{
header("location:NotLocalhost.html");
exit;
}
}
else{
header("Location:NOREF.html");
exit;
}
?>
This code works fine in all browsers except firefox. coz In firefox $_SERVER["HTTP_REFRER"] becomes null and NOREF.html is displayed.
Also in firefox when the script is accessed by another html or php script then works fine, but when is accessed vai swf movie which is in turn <embeded> in html page. Then the REFERER becomes null.
Any ideas? How can I solve this?

drag-and-drop image upload not working on server

I am trying to implement a drag-and-drop image upload.
I found a rather simple script online and adapted to my use.
On my local installation the file uploads perfectly fine, but not on the server.
From my debugging attempts the $_SERVER['HTTP_X_FILENAME'] does not even get set by php.
I tried the following:
- Making sure that the upload folder is set to 755
- Changing the php temporary upload path and increasing the maximum allowed file size
No php or js errors of any kind occur.
Since I have the die(print_r($_SERVER)); in the php, I get the $_SERVER dump using the chrome inspector, it does not contain HTTP_X_FILENAME index.
My php is:
<?php
$fn = (isset($_SERVER['HTTP_X_FILENAME']) ? $_SERVER['HTTP_X_FILENAME'] : false);
if ($fn) {
// AJAX call
file_put_contents(
'../usr/photos/' . $fn,
file_get_contents('php://input')
);
echo "$fn uploaded";
exit();
}
else {
// form submit
if(!$_FILES['fileselect']) die(print_r($_SERVER));
else $files = $_FILES['fileselect'];
foreach ($files['error'] as $id => $err) {
if ($err == UPLOAD_ERR_OK) {
$fn = $files['name'][$id];
move_uploaded_file(
$files['tmp_name'][$id],
'../usr/photos/' . $fn
);
echo "<p>File $fn uploaded.</p>";
}
}
}
The js is as follows:
//Drag and drop photo upload
(function() {
// getElementById
function $id(id) {
return document.getElementById(id);
}
// output information
function Output(msg) {
var m = $id("messages");
m.innerHTML = msg + m.innerHTML;
}
// file drag hover
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
e.target.className = (e.type == "dragover" ? "hover" : "");
}
// file selection
function FileSelectHandler(e) {
// cancel event and hover styling
FileDragHover(e);
// fetch FileList object
var files = e.target.files || e.dataTransfer.files;
// process all File objects
for (var i = 0, f; f = files[i]; i++) {
ParseFile(f);
UploadFile(f);
}
}
// output file information
function ParseFile(file) {
/*Debug*/
Output(
"<p>File information: <strong>" + file.name +
"</strong> type: <strong>" + file.type +
"</strong> size: <strong>" + file.size +
"</strong> bytes</p>"
);
// display an image
if (file.type.indexOf("image") == 0) {
var reader = new FileReader();
reader.onload = function(e) {
Output(
"<p>" +
//"<strong>" + file.name + ":</strong><br />" +
'<img width="130" height="100" src="' + e.target.result + '" />' +
'<br />' +
'<input type="text" name="photo_name" value="'+ file.name +'" />' +
'<br />' +
'<input type="text" name="photo_caption" value="Caption" /></p>'
);
}
reader.readAsDataURL(file);
}
// display text
if (file.type.indexOf("text") == 0) {
var reader = new FileReader();
reader.onload = function(e) {
Output(
"<p><strong>" + file.name + ":</strong></p><pre>" +
e.target.result.replace(/</g, "<").replace(/>/g, ">") +
"</pre>"
);
}
reader.readAsText(file);
}
}
// upload JPEG files
function UploadFile(file) {
// following line is not necessary: prevents running on SitePoint servers
if (location.host.indexOf("sitepointstatic") >= 0) return
var xhr = new XMLHttpRequest();
if (xhr.upload && (file.type == "image/jpeg" || file.type == "image/png") && file.size <= $id("MAX_FILE_SIZE").value) {
// create progress bar
var o = $id("progress");
var progress = o.appendChild(document.createElement("p"));
progress.appendChild(document.createTextNode("upload " + file.name));
// progress bar
xhr.upload.addEventListener("progress", function(e) {
var pc = parseInt(100 - (e.loaded / e.total * 100));
progress.style.backgroundPosition = pc + "% 0";
}, false);
// file received/failed
xhr.onreadystatechange = function(e) {
if (xhr.readyState == 4) {
progress.className = (xhr.status == 200 ? "success" : "failure");
}
};
// start upload
xhr.open("POST", $id("upload").action, true);
xhr.setRequestHeader("X_FILENAME", file.name);
xhr.send(file);
}
}
// initialize
function Init() {
var fileselect = $id("fileselect"),
filedrag = $id("filedrag"),
submitbutton = $id("submitbutton");
// file select
fileselect.addEventListener("change", FileSelectHandler, false);
// is XHR2 available?
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// file drop
filedrag.addEventListener("dragover", FileDragHover, false);
filedrag.addEventListener("dragleave", FileDragHover, false);
filedrag.addEventListener("drop", FileSelectHandler, false);
filedrag.style.display = "block";
// remove submit button
submitbutton.style.display = "none";
}
}
// call initialization file
if (window.File && window.FileList && window.FileReader) {
Init();
}
})();
Thank you in advance.
You probably will have solved your problem now, but I'm posting this solution here to help others who come here with the same problem. In your js, there is a line that reads
xhr.setRequestHeader("X_FILENAME", file.name);
but should read
xhr.setRequestHeader("X-FILENAME", file.name);
since underscores are deprecated in later Apache releases (see also
Header names with underscores ignored in php 5.5.1 / apache 2.4.6)
I had this problem on one of my Ubuntu WAMP installations. Your upload URL (the POST URL specified on the Javascript side of things) needs to be a fully qualified path not a relative path. I can't see the value however but seems to be the value of whatever $id("upload").action is in your code. You can confirm this is the cause by looking at the apache logs if you have access to them. If you see 404 errors when trying to send a file then this is your problem. Thats assuming the request even hits your server at all.

How to GET variable as instance from PHP after POST by flash actionscript

Hi I'm working on actionscript, saving a raw image from camera then POST with save.php then
I want save.php echo back the variable which is a file name that have just generated by save.php to actionscript
see this line:
var urlParameter:String = "images/test_01.php?img=" + "myfileURL";
navigateToURL(new URLRequest(urlParameter), "_blank");
Thanks in advance
this is AS3 code
function onSaveJPG(e:Event):void{
var myEncoder:JPGEncoder = new JPGEncoder(100);
var byteArray:ByteArray = myEncoder.encode(bitmapData);
var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
var saveJPG:URLRequest = new URLRequest("save.php");
saveJPG.requestHeaders.push(header);
saveJPG.method = URLRequestMethod.POST;
saveJPG.data = byteArray;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, sendComplete);
urlLoader.load(saveJPG);
function sendComplete(event:Event):void{
warn.visible = true;
addChild(warn);
warn.addEventListener(MouseEvent.MOUSE_DOWN, warnDown);
warn.buttonMode = true;
}
function warnDown(e:MouseEvent):void{
var urlParameter:String = "images/test_01.php?img=" + "myfileURL";
navigateToURL(new URLRequest(urlParameter), "_blank");
// navigateToURL(new URLRequest("images/"), "_blank");
// +saveJPG:URLRequest
// navigateToURL(new URLRequest("images/test_01.php?img=+saveJPG:URLRequest"), "_blank");
warn.visible = false;
}
} // move onSave JPG
} close to here instead of after sendComplete
warn.visible = false;
this is save.php
<?php
if(isset($GLOBALS["HTTP_RAW_POST_DATA"])){
$jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$img = $GET["img"];
$filename = "images/poza". mktime(). ".jpg";
file_put_contents($filename, $jpg);
echo "thisPic=" . $filename;
// echo $filename;
} else{
echo "Encoded JPEG information not received.";
}
?>
In your case you are just using mktime() for the file name, and images/poza is hard coded. You can post the file name along the jpeg data from flash, and when onSaveJPG is called you simply display the file name to the user.
Below is example of how you can send file_name.
var JPGFileName = YOUR TIME FUNCTION
var saveJPG:URLRequest = new URLRequest("save.php?file_name=" + JPGFileName);
saveJPG.requestHeaders.push(header);
saveJPG.method = URLRequestMethod.POST; saveJPG.data = byteArray;

Categories