I want to save a screenshot from my Flex app on the Webserver (LAMP).
Here is the Flex code:
private function getBitmapData( target : UIComponent ) : BitmapData
{
var bd : BitmapData = new BitmapData( target.width, target.height );
var m : Matrix = new Matrix();
bd.draw( target, m );
return bd;
}
Now, how do I send / receive this data to the server?
You are going to have to use a HttpService to post the data to a page on your website. When I implemented this I posted the Image data as a Base64 encoded string to a PHP page that used the GD library to save it to a png file on the server. Here is a simplified example of what my code looked like
Flex Code
public function saveImg():void{
var bd:BitmapData = new BitmapData(mycanvas.width,mycanvas.height);
bd.draw(mycanvas);
var ba:ByteArray = PNGEncoder.encode(bd);
var encoded:String = Base64.encodeByteArray(ba);
var objSend:Object = new Object;
objSend.data = encoded;
objSend.filename = _imgResult;
writeImage.send(objSend);
}
<mx:HTTPService id="writeImage" url="/saveImage.php" method="POST" resultFormat="text" result="resultHandler(event)"/>
PHP File (saveImage.php)
<?php
//check for the posted data and decode it
if (isset($_POST["data"]) && ($_POST["data"] !="")){
$data = $_POST["data"];
$data = base64_decode($data);
$im = imagecreatefromstring($data);
}
//make a file name
$filename = "test"
//save the image to the disk
if (isset($im) && $im != false) {
$imgFile = "/etc/www/html/".$filename.".png";
//delete the file if it already exists
if(file_exists($imgFile)){
unlink($imgFile);
}
$result = imagepng($im, $imgFile);
imagedestroy($im);
echo "/".$filename.".png";
}
else {
echo 'Error';
}
?>
On the flex side I am using the Base64Encode utilty from dynamicflash, but now that there is one built into flex you could use that instead. In your php config you will need to make sure you have the GD library enabled so that you can save the image.
Of course this is a very simple example and does not take into account all the error handling and security concerns needed, but should provide you a good base to get going with.
Related
I am trying to upload image taken from webcam. I use canvas for showing that image and send base64_encoded json data by POST method to PHP and therefore in PHP decode the data and try to create an image by file_put_contents. But the uploaded image is corrupted every time. I used header("Access-Control-Allow-Origin: *") in PHP also. I also checked that the file_get_contents is enabled in the server. What may be the error? Please help.
My code is:
JS:
// Trigger photo take
var imagedata;
document.getElementById('snap').addEventListener('click', function() {
$('#canvas').show();
context.drawImage(video, 0, 0, 640, 480);
$('#upload-button').removeAttr("disabled");
var image = new Image();
image.src = canvas.toDataURL();
imagedata = image.src;
$('#webimage').val(imagedata);
});
PHP:
header("Access-Control-Allow-Origin: *");
$input_data = json_decode(trim(file_get_contents('php://input')), true);
$base = $input_data['image'];
$destination_directory = "uploads/";
$file_name = time();
$file_name = $file_name.'.png';
$targetPath = $destination_directory . $file_name;
$input_data = base64_decode($base);
file_put_contents($targetPath, $input_data);
Did you ever inspect the data url of an image? It looks like this:
image/gif;base64,R0lGODlhyAAiALM...DfD0QAADs=
As you can see the actual base64 encoded representation of the binary content of the image starts after the comma. All you have to do is change:
$base = $input_data['image'];
to:
// php >= 5.4
$base = explode(',', $input_data['image'])[1];
// php < 5.4
list (, $base) = explode(',', $input_data['image']);
so the base64_decode function receives proper base64 string.
You are also missing proper validation inside your script:
validate JSON input was decoded properly
validate image key exists in the resulting array
validate base64_decode did decode the string
validate resulting image is a valid image (malicious users can embed PHP code for instance inside the image)
This way you can be 99% sure your server won't get compromised in the future.
I am using quilljs for my editor. All my data are handle by mysql database. I am using Angularjs 1.x and for backend Cakephp is my frame-work.
I am currently trying to build a forum kind of page in which I want to save multiple images along with text which will be formatted using quilljs
<p>sd<img src="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgA....SUVORK5CYII=" alt="i am image"><b>it is image of earth</b></p>
This is what currently storing in my database. Now if there is multiple big images come in then size of field will be too much high there for I want to upload image inside severside folder and want to print image address inside image tag like:
<p>sd<img src="../img/709f2d0be9d13c645037f1b9bb066b00a6d7/image1.jpg" alt="i am image"><b>it is image of earth</b></p>
So I can fetch image directly from given folder.
i have done small trick with quilljs. i have put some code inside quilljs which send image toward my php script on line number 8663 after if (typeof value === 'string') this statement i have added script which sends image value to my php script
var img = {
'img' : value
}
$.ajax({
url: "../Writers/writerCertificateupload",
data: img,
contentType: undefined,
type: 'post'
}).success(function(path){
node.setAttribute('src', path);
})
where node.setAttribute('src', path); sets path which i am returning from php script it sets it on image tag i.e <img src="../img/709f2d0be9d13c645037f1b9bb066b00a6d7/image1.jpg">
and then it sets it inside editor and then we can save that data within editor. this is how i have solve this problem.
my php code is
public function writerCertificateupload()//pending
{
$id = $this->Auth->user('id');
$this->autoRender=false;
define('UPLOAD_DIR', 'files/post/');
$img = $_POST['img'];
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpg';
$success = file_put_contents($file, $data);
$file = "../".$file;
print $success ? $file : 'Unable to save the file.';
}
You need to create custom image handler (like here) and check base64 string length with fileReader.
I had the same problem in Angular(primeNg) and ended up with the below solution, Btw plz notice that you only need to monitor the editor text change and do some modification like below:
public async handleTextChange(event: any) {
try {
const operations = event.delta.ops;
for (let i = 0; i < operations.length; i++) {
const op = operations[i];
const opType = Object.keys(op)[0] as any;
if (opType == 'insert' && op['insert'].hasOwnProperty('image')) {
this.isLoading = true;
const uploadedImageURL = await this.uploadImage(op['insert'].image);
this._cdr.detectChanges();
const newContent = event.htmlValue.replace(
op['insert'].image,
uploadedImageURL
);
this.editorContent = newContent;
this.contentChanged.emit(newContent);
}
}
} catch (error) {
this.editorContent = this.editorContent + '<br/><br/>';
} finally {
this.isLoading = false;
this._cdr.detectChanges();
}
The upload method will be like this, by the way the upload logic will be depends on your own logic though more or less it's the same:
async uploadImage(dataURL: string): Promise<string> {
const ImageData: FormData = new FormData();
let fileType = dataURL.substring(
dataURL.indexOf(':') + 1,
dataURL.lastIndexOf(';')
);
let fileExtension = fileType.split('/');
const file = new File(
[dataURL],
`file${new Date().getTime()}.${fileExtension[1]}`,
{ type: fileType }
);
ImageData.append('file', file);
const uploadedImageURL = await this._imageUploaderService
.uploadedImage(ImageData)
.toPromise();
return uploadedImageURL ;
}
The component html would be like this
<p-editor
name="editorContent"
[(ngModel)]="editorContent"
[id]="editorId"
[style]="{ height: '320px' }"
(onTextChange)="handleTextChange($event)"
></p-editor>
<app-spinner *ngIf="isLoading == true"></app-spinner>
It's worth mentioning that I used this for p-editor which belongs to primeNg in angular projects
I need to create thumbnail without ffmpeg because I have to deploy site on shared hosting and ffmpeg is not available on shared hosting.
Can someone suggest some solution?
If the video can be played back in the browser you could try using the Canvas feature of html5 to playback the video in a canvas and then post a still from that video to your server using javascript... Maybe you could even automate it, or if you only have a few dozen videos do it by hand...
The following is some jquery flavored javascript to upload a base64-encoded jpg in order to get you started. (Mashed up from several different projects, so untested and probably a security nightmare.)
<script>
var vidDOM = $('article').children('video');
var vid = vidDOM.get(2);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
vidDOM.bind({
'paused':function () {
vid.width = canvas.width = vid.offsetWidth;
vid.height = canvas.height = vid.offsetHeight;
var $this = this;
ctx.drawImage($this, 0, 0, vid.width, vid.height);
uploadbase64();
}
})
function uploadbase64(){
canvasData = canvas.toDataURL("image/jpeg");
var ajax = new XMLHttpRequest();
ajax.open("POST",'ImageUpload.php?filename='+vidDOM.id,false);
ajax.setRequestHeader('Content-Type', 'application/upload');
ajax.send(canvasData);
}
</script>
And here is a bit of php to accept the upload.
<?php
$filename =$_GET['filename'];
if (file_get_contents('php://input')){
// Remove the headers (data:,) part.
$filteredData=substr(file_get_contents('php://input'), strpos(file_get_contents('php://input'), ",")+1);
// Need to decode before saving since the data we received is already base64 encoded
$decodedData=base64_decode($filteredData);
//create the file
if($fp = fopen( $filename, 'wb' )){
fwrite( $fp, $decodedData);
fclose( $fp );
} else {
echo "Could not create file.";
}
}
echo "Created image ".$filename;
?>
I am working with an app where I am unable to post the File to the server. Therefor I have chose to send it as a string to the server, and remake it to a file using PHP. Below is the javascript code I am using to convert the image to a string.
var file = document.getElementById("fileForUpload").files[0];
if (file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (evt) {
document.getElementById("fileContents").value = utf8_to_b64(evt.target.result);
}
reader.onerror = function (evt) {
document.getElementById("fileContents").value = "error reading file";
}
}
function utf8_to_b64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
On the server side I'm doing this
header("Content-type: image/png");
$data = preg_replace('/\s+/', '', $data);
echo base64_decode($data);
exit;
But it says that the image cannot be displayed because it contains errors.
Can you please tell me what I am doing wrong here? I am correctly receiving the Base64 encoded string to the server.
Edit
Please note that I am trying to post the string through an HTML form.
Easy:
$imagedata = file_get_contents("/path/to/image.jpg");
// alternatively specify an URL, if PHP settings allow
$base64 = base64_encode($imagedata);
bear in mind that this will enlarge the data by 33%, and you'll have problems with files whose size exceed your memory_limit.
My problem is as follows...
I have a screen in which the user can select a PNG image from its computer, using this:
<input id='icon' type='file' accept='image/png' style='width:400px; height:20px' onchange='llenarThumbnail(this)'>
<img id='thumb' src='#'>
When the user selects the image, a thumbnail is shown automatically, using onclick='llenar Thumbnail(this)', like this:
function llenarThumbnail(input){
if (input.files && input.files[0]){
var reader = new FileReader();
reader.onload = function (e){
$('#thumb').attr('src', e.target.result).width(48).height(48);
};
reader.readAsDataURL(input.files[0]);
}
}
Then, when the user clicks on the proper button to upload the image (not a submit button), I do the following to encode the image into Base64:
function getBase64Image(img){
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
console.log(dataURL);
return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}
Then, using AJAX I send this encoded image data to the server, and a PHP script does the following:
$binary=base64_decode($imagen_data);
header('Content-Type: bitmap; charset=utf-8');
$file = fopen($icono, 'wb');
fwrite($file, $binary);
fclose($file);
As I was printing diferent alerts along the process, I could see that the encoding was performing (i'm not so sure if correctly or not), and PHP receives the data and creates the PNG file, but when I open the image, the image is empty, there's no data... Thats why I'm asking if this to methods are compatible... I guess they are because they're both Base64... But if its not this, then what am i doing wrong???
Please, I'm tired of looking for this all over the internet! I need some answers! Thank you!
Without seeing your ajax POST, here's a Wild Guess:
Try leaving the prefix on until the URL gets to php.
Which php server are you using?
Some other usual gotchas:
Make sure you have properly set up your upload directory.
Make sure you have permissions set properly on the upload directory.
Client Side:
// create a dataUrl from the canvas
var dataURL= canvas.toDataURL();
// post the dataUrl to php
$.ajax({
type: "POST",
url: "upload.php",
data: {image: dataURL}
}).done(function( respond ) {
// you will get back the temp file name
// or "Unable to save this image."
console.log(respond);
});
Server File: upload.php
<?php
// make sure the image-data exists and is not empty
// php is particularly sensitive to empty image-data
if ( isset($_POST["image"]) && !empty($_POST["image"]) ) {
// get the dataURL
$dataURL = $_POST["image"];
// the dataURL has a prefix (mimetype+datatype)
// that we don't want, so strip that prefix off
$parts = explode(',', $dataURL);
$data = $parts[1];
// Decode base64 data, resulting in an image
$data = base64_decode($data);
// create a temporary unique file name
$file = UPLOAD_DIR . uniqid() . '.png';
// write the file to the upload directory
$success = file_put_contents($file, $data);
// return the temp file name (success)
// or return an error message just to frustrate the user (kidding!)
print $success ? $file : 'Unable to save this image.';
}
I could not get markE solution to work, had to change the data modification :
From :
$parts = explode(',', $dataURL);
$data = $parts[1];
$data=base64_decode($data)
To :
$img = str_replace('data:image/png;base64,', '', $dataURL);
$img = str_replace(' ', '+', $img);
$data=base64_decode($img);
Method from