Reputation: 208
I have a route which I use to request images, something like this:
/api/image
it returns the body the file data, something like:
����JFIF��C��C��� ��
�����+�}Yϭ�F39M>���������>���;��ˋ��uXʽ�w�ڤx\-[2g��k�S���H���m
[�V?[_W����#��v��}6�[��F�F�%����n�...
what I'm trying to do is something like this:
<canvas>
then i did this:
code:
var canvas = $('canvas');
var blob = new Blob([file], {type: 'image/png'});
var url = URL.createObjectURL(blob);
var img = new Image;
var ctx = canvas.getContext('2d');
$(img).on('load',function(event) {
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(url);
}).each(function(){
if(this.complete) { $(this).load() }
});
img.src = url;
I also appended the file directly to the image source attribute like:
img.src = 'data:image/png;base64,' + file
but it didn't work
What I get is that the resource is not found and it throws a 404 error:
> GET blob:http://localhost:3000/2a86de11-b565-4578-8ec1-2c20cbdae739 404 (Not Found)
I'm a bit confused, what am I doing wrong?
edit: i just did this:
var blob = new Blob([file], {type: 'image/png'});
var reader = new FileReader();
reader.onload = function (e) {
suggestion.img.attr('src', e.target.result);
};
reader.readAsDataURL(blob);
but it doesnt show the image either
Upvotes: 1
Views: 2140
Reputation: 13109
Well, the top data you've shown is binary and as such, just prepending the dataURL stuff wont work. You'll need to either do something different with the binary data or send back actual base64 encoded data instead.
Here's a compound example. It shows:
base64.php
<?php
// usefull for images without CORS header
if (isset($_GET['filename']) == true)
{
$filename = urldecode( $_GET['filename'] );
$data = file_get_contents($filename);
$finfo = new finfo(FILEINFO_MIME);
$mimeType = $finfo->buffer($data);
Header("Content-Type: $mimeType"); // use the currently detected mime-type
echo $data;
die;
}
if (isset($_FILES['upload']) == true)
{
$alterResult = true;
// GD wont load svgs :(
if (strcmp(trim($_FILES['upload']['type']),"image/svg+xml") == 0)
$alterResult = false;
// expecting a form element with the type of 'file' and the name of 'upload' - accepting 1 file max
$data = file_get_contents( $_FILES['upload']['tmp_name'] );
// draw copy of image, invert the colours, guassian blur 5 times, draw inverted,bluury image beside unaltered copy
if ($alterResult == true)
{
$mImage = imagecreatefromstring ($data);
$output = imagecreatetruecolor(imagesx($mImage) * 2, imagesy($mImage));
imagesavealpha ( $mImage , true);
imagesavealpha ( $output , true);
imagecopy($output, $mImage, 0, 0, 0, 0, imagesx($mImage) - 1, imagesy($mImage) - 1);
imagefilter($mImage,IMG_FILTER_NEGATE);
imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($mImage,IMG_FILTER_GAUSSIAN_BLUR);
imagecopy($output, $mImage, imagesx($mImage), 0, 0, 0, imagesx($mImage) - 1, imagesy($mImage) - 1);
Header("Content-Type: image/png");
imagepng($output);
imagedestroy($mImage);
imagedestroy($output);
die;
}
// it's an svg, so just return byte-for-byte what we received
else
{
$finfo = new finfo(FILEINFO_MIME);
$mimeType = $finfo->buffer($data);
$mimeType = preg_replace("/text\/plain/", "image/svg+xml", $mimeType); // svgs are wrongly reported as text files
Header("Content-Type: $mimeType"); // use the currently detected mime-type
echo $data;
die;
}
}
?><!doctype html>
<html>
<head>
<script>
function byId(id){return document.getElementById(id)}
function newEl(tag){return document.createElement(tag)}
window.addEventListener('load',onDocLoaded);
function onDocLoaded(evt)
{
byId('fileInput').addEventListener('change', onFileChosen);
// cross origin test
var can = newEl('canvas');
var ctx = can.getContext('2d');
var srcImg = byId('crossOrigin');
can.width = srcImg.naturalWidth;
can.height = srcImg.naturalHeight;
ctx.drawImage(srcImg, 0,0);
document.body.appendChild(can);
console.log( can.toDataURL() );
}
function ajaxGet(url, onLoad, onError)
{
var ajax = new XMLHttpRequest();
ajax.onload = function(evt){onLoad(this);}
ajax.onerror = function(evt){onError(this);}
ajax.open("GET", url, true);
ajax.send();
}
function ajaxGetBinary(url, onLoad, onError)
{
var ajax = new XMLHttpRequest();
ajax.responseType = 'arraybuffer';
ajax.onload = function(evt){onLoad(this);}
ajax.onerror = function(evt){onError(this);}
ajax.open("GET", url, true);
ajax.send();
}
function ajaxPostForm(url, formElem, onLoad, onError)
{
var ajax = new XMLHttpRequest();
ajax.open("POST", url, true);
ajax.responseType = 'arraybuffer';
ajax.onload = function(evt){onLoad(this);}
ajax.onerror = function(evt){onError(this);}
ajax.send( new FormData(formElem) );
}
function onFileChosen(evt)
{
// just clear the images if no file selected
if (this.files.length < 1)
{
byId('beforeImg').src = '';
byId('afterImg').src = '';
return;
}
var file = this.files[0]; // used to set the mime-type of the file when we get it back
/*
==========Before upload/download==========
*/
let fileReader = new FileReader();
fileReader.onload = function(evt){byId('beforeImg').src=this.result;}
fileReader.readAsDataURL(file);
/*
==========After upload/download==========
send the file to the backend (also this source-file), then the back-end will read the temporary file and output it.
we catch this binary output and make an image element with it
*/
ajaxPostForm('<?php echo $_SERVER['PHP_SELF']; ?>', byId('mForm'), onPostOkay, function(){});
function onPostOkay(ajax)
{
let arrayBuffer = ajax.response;
if (arrayBuffer)
{
let byteArray = new Uint8Array(arrayBuffer);
let blob = new Blob([byteArray], {type: file.type });
byId('afterImg').src = URL.createObjectURL(blob);
}
}
}
</script>
<style>
.panel
{
display: inline-block;
padding: 8px;
border-radius: 8px;
border: solid 1px black;
text-align: center;
}
</style>
</head>
<body>
<!-- RESULT of below: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA......." -->
<img id='crossOrigin' src='base64.php?filename=https%3A%2F%2Fmy.totalwellbeingdiet.com%2Fimg%2Fcsiro%2Flogos%2Fcsiro.png'/>
<!-- RESULT of below: "Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported." -->
<!-- <img id='crossOrigin' src='https://my.totalwellbeingdiet.com/img/csiro/logos/csiro.png'/> -->
<form id='mForm' method='post' enctype="multipart/form-data">
<input id='fileInput' type='file' name='upload'/>
</form>
<div class='panel'>
<img id='beforeImg'/><br>
<strong>Before upload</strong>
</div>
<div class='panel'>
<img id='afterImg'/><br>
<strong>After upload/mod/download</strong>
</div>
</body>
</html>
Upvotes: 2
Reputation: 37965
You should not construct a blob yourself, the responseType should be blob
And don't use jquery's Ajax method for binary...
Upvotes: 0