I am am writing a program that pulls a dataURL from a canvas element and sends it server side to be converted back to a jpg and saved. What I need to do now, is to programmatically get this image from the server and post it using another ajax function as a multipart/form-data encoded form. There is some code that cannot be modified and it is expecting this type of post.
To be specific: how do I take an image from the server and put it into a POST of enctype="multipart/form-data" such that the code receiving the request sees it as if it were an post coming from a regular form. All of this using Jquery or JavaScript Ajax.
Extra info: The code being posted to is in ASP classic. I am using PHP to convert the DataURL.
PHP Code:
//Get the base-64 string from data
$data=$_POST['img_val'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents('filename.png', $data);
$images_orig = imagecreatefrompng('filename.png');
$photoX = ImagesX($images_orig);
$photoY = ImagesY($images_orig);
$images_fin = ImageCreateTrueColor(650, 650);
ImageCopyResampled($images_fin, $images_orig, 0, 0, 0, 0, 650+1, 650+1, $photoX, $photoY);
imagejpeg($images_fin, NULL, 100);
ImageDestroy($images_orig);
ImageDestroy($images_fin);
The above code can be use to return either a binary Image File or to save the contents to disk and return an image URL. I'm not sure which will be more useful to my end goal.
Thanks to All.
So for those who need a solution to something like this, the answer is a bit complicated. The above PHP code does properly convert the image from a dataURL to a png, and then resizes it as a jpg. The proper way to make a multipart/form-data Post from ajax goes like this:
var url = "example.php"
var image_as_blob = previousAjaxRequest(); //use xhr.responseType = "blob" and a GET request to grab server image
var form = new FormData();
form.append('image_variable_name', image_as_blob, 'file_name.extension'); //the third argument seemed to make all the difference in server code seeing the file correctly.
$.ajax({
url: url,
type: 'post',
data: form,
cache: false,
contentType: false, //required for multipart
processData: false //required for multipart
}).done(function( data ) {
//do what you want with returned data
});
Related
I would like to have a button that when clicked gets a file (in this case a dynamically generated PDF) from a (predefined) URL on the same domain, and sends it to a (php) backend to be saved.
I am guessing that the best way to do this is to somehow load the file returned by the URL into a javascript variable, base64 encode it and send that to the backend with an ajax POST. Then on the backend I would base64 decode it and save it as a regular file.
Is this the right approach, or is there a better way to do it?
If this is the right approach, the part I am not sure how to do is getting the file from the URL into a variable. Once it's there, I guess I can use btoa() to base64 encode it. The other thing I am not 100% sure about is whether that will be compatible with base64_decode() in PHP for when I decode it?
Update
You say, the URL is predefined, and you don't know how to get in into a javascript variable. I guess, the URL is defined in the backend (PHP). So you could simply set/inject it in the client side code (javascript) with PHP.
Don't post the URL back from the client to the server, as there seems to be no need for that, and the URL could easily be changed by the user (security issue)!!!
So, maybe a better way would be to keep the URL on the server side, and inject it in the client page using php, without posting it back to the server.
Original answer
This answer is only appropriate if the client generates the URL and you have a secure way to verify it, as every client side input has to be treated as potential harmful user input.
In my opinion this is the absolutely right approach. Yes, you should base64 encode your variable. You could put the base64 encoded string in a json object and post this json object via ajax, or post it as plain text in your post body. Make sure to verify this as a client input!
I see no reason why btoa()/base64_decode() should not work. Base64 is platform independent.
I figured it out. It's a mix of vanilla and jQuery because the vanilla is from this article and the project I am working in already has jQuery available for $.ajax to make the POST to the backend easier.
var oReq = new XMLHttpRequest();
var fileUrl = '[URL from PHP]';
oReq.open("GET", fileUrl, true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
let arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
let binaryText;
let byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
binaryText+=String.fromCharCode( byteArray[ i ] );
}
$.ajax({
type: "POST",
url: "/path/to/backend-upload",
data: {"fileData":btoa(binaryText)},
success: function(resultData){
alert("File Uploaded");
}
});
}
};
oReq.send(null);
and in the PHP backend:
file_put_contents("/path/to/destination", base64_decode($_POST['fileData']));
I have written a simple JS script, that saves mouse positions in an array, which I then send to a php function via AJAX. It works, and saves the recieved data, but the problem is how it is saved, i.e. i would expect to have a normal output of the x and y position as is: [x1,y1],[x2,y2],[x3,y3],...
But what i get is something like this:
a:63:{i:0;a:2:{i:0;i:527;i:1;i:1010;}i:1;a:2:{i:0;i:490;i:1;i:1205;}i:2;a:2:{i:0;i:588;i:1;i:1311;}i:3;a:2:{i:0;i:615;i:1;i:1368;}i:4;a:2:{i:0;i:553;i:1;i:1474;}i:5;...
I thought if i encode it in JSON format that it would save as i thought, but i dont understand why the output is as it is. Any ideas?
The JS code is as follows:
window.onbeforeunload = function() {
var jsonString = JSON.stringify(tabela);
$.ajax({
type: 'POST',
url: 'process.php',
data: {
text1: jsonString
}
});
}
And the PHP side is this:
$text1 = json_decode(stripslashes($_POST['text1']));
$string_data = serialize($text1);
file_put_contents("your-file.txt", $string_data);
The content looks like this in the file, because you passed the array through serialize function. In order to "decode" file content, use unserialize.
If you want to have more human-readable file content, just store the JSON string in the file ($_POST['text1'] directly) or instead of serialize use json_encode again before calling file_put_contents.
made a websitem, or trying to, where you can take a picture with your webcam and then upload it to the server, but ive found some inspiration in a guy that uses PHP and i wanna avoid it as much as posible. so what i have now in my .html for uploading is the picture is:
// Upload image to sever
document.getElementById("upload").addEventListener("click", function(){
var dataUrl = canvas.toDataURL("images/", 0.85);
$("#uploading").show();
$.ajax({
type: "POST",
url: "html5-webcam-save.php",
data: {
imgBase64: dataUrl,
//user: "Joe"
}
and then the reference(html5-webcam-save.php):
<?php
$rawData = $_POST['imgBase64'];
$filteredData = explode(',', $rawData);
$unencoded = base64_decode($filteredData[1]);
$datime = date("Y-m-d-H.i.s", time() ) ; # - 3600*7
//$userid = $_POST['userid'] ;
// name & save the image file
$fp = fopen('images/'.$datime.'-'.$userid.'.jpg', 'w');
fwrite($fp, $unencoded);
fclose($fp);
so my question, anyone now how to upload it to the server or just the "images" folder in the root of the site, without the need for PHP.
to be honest, the reason i dont want the PHP is because i simply cant get it to work properly on the server side, and iam lost when it comes to php. So can this be done with for instance C#/Javascript?
"..without the need for PHP"
You can't. You need a server side language to receive the data from raw http, convert it back from base64 text to image and then write it to disc. It could be PHP, c#, nodejs javascript, but there will always be a server side controller handling all this. You can't access server file system from client javascript for obvious security reasons.
I have a Uint8Array which have 10000 bytes on Javascript side.
var data = new Uint8Array(10000) ;
I want to send it to PHP and create a file with it:
$.ajax({
url:'saver.php',
type: 'POST',
contentType: 'application/octet-stream',
data:data,
processData: false
});
This ajax is sending data (I see it on "Request Payload" section on console) but there is no $_POST record, $_POST array is empty, just silent. How to grab it properly?
This seems to be a known behavior.
For an array of 10000 bytes, you should be able to use
$rawPost = file_get_contents('php://input');
to get your data from the request instead of checking the $_POST variable.
Note that this method loads the data in-memory, so if the data are too large, you will get an error.
In my case.
I get binary file from JS request array : $file['content'] format of Uint8Array.
<?php
$packed = pack("c*", ...$file['content']);
I am writing a crawler and needs to download file generated after a form request using POST.
I have successfully used this.download(url,'POST',Params) for regular forms.
One of the sites has many fields using the same name, thus preventing me from using the regular download method.
After trying a lot of things, I tried with $.ajax() and __utils.sendAJAX() to process the form like this:
response = this.evaluate(function(){
url=...
params = $('form#theirForm').serialize();
data = __utils__.sendAJAX(url, 'POST', params,false,{contentType:"application/x-www-form-urlencoded"});
return __utils__.encode(data);
});
function decode_base64(s) { var e={},i,k,v=[],r='',w=String.fromCharCode; var n=[[65,91],[97,123],[48,58],[43,44],[47,48]]; for(z in n){for(i=n[z][0];i<n[z][1];i++){v.push(w(i));}} for(i=0;i<64;i++){e[v[i]]=i;} for(i=0;i<s.length;i+=72){ var b=0,c,x,l=0,o=s.substring(i,i+72); for(x=0;x<o.length;x++){ c=e[o.charAt(x)];b=(b<<6)+c;l+=6; while(l>=8){r+=w((b>>>(l-=8))%256);} } } return r; }
casper.then(function() {
utils.dump(response);
fs.write("test.zip",decode_base64(response),'w');
});
The codes returns me base64 data which I convert and store in a test.zip file.
But I juste can't uncompress it, says it is corrupted.
I dump the data of a correct zip file =>
PK^C^D^T^#^H^#^H^#<F4><89><96>F^#^#^#^#^#^#^#^#^#^#^#^#?^#^#^#fourniture denr<E9>es alimentaires - dietetique infantile\CCAP.pdf<AC><BC>^ET\K<D3><F7>;^D<B7><U+0B81>^#<C1><99>^Y^F'^D<B7><E0>^D^ON<90><E0><EE><EE><EE>^Dwww'^P<9C>^D^H<EE>^^܂<C3>%'<CF>9<E7><C9><F7><U+07B5><BE>7<F7>f^SVOzf
Compared it with the first line of my file :
PK^C^D^T^#^H^#^H^#)_^M^#^#^#^#^#^#^#^#^#^#^#^#^#b^#^#^#fourniture denr<FD>es alimentaires - dietetique infantile\Bordereau de prix dietetique infantile.xlsx<FD>zuT<FD>I<FD><FD><FD><FD>^^4hp^M^D^M^R^H<FD>.<FD><FD>}p<FD>3<FD>kpw<FD>#pw^M<FD><FD>^R4<FD>Gv<FD>~<FD>[<FD><FD><FD><FD><FD>
Anyone has an idea of what could have gone wrong?
I have tried so many things (encoding tools, encoding settings, dumping from the chrome console to get pure base64, etc.)
I don't understand why it is related to latin-1 or utf8 encoding, since a website asks me to select which encoding to use. Tried both.
casper.download() happily accepts a serialized form instead of an object, so you can still use it. You just have to serialize the form in the page context beforehand:
var formData = casper.evaluate(function(){
return $('form#theirForm').serialize();
});
var url;
casper.download(url, targetFile, 'POST', params);
The only problem might be, that another mimeType is used: "text/plain; charset=x-user-defined".
In that case, you will have to recreate the whole cascade of functions that go into casper.download():
var url;
var response = casper.evaluate(function(url){
var params = $('form#theirForm').serialize();
var data = __utils__.sendAJAX(url, 'POST', params, false);
return __utils__.encode(data);
}, url);
var cu = require('clientutils');
fs.write("test.zip", cu.decode(response), 'wb');
"application/x-www-form-urlencoded" is used by default for __utils__.sendAJAX().