Displaying a png image from base64 data - angularjs

We are printing labels, which are created by a third party. We serve them directly, passing the base64 data into a blank window, so the user can print it himself.
No matter how many ways I try it, I cannot get the image itself to display.
Here's an excerpt of the data returned from the server (in any other display, it is full of � characters):
PNG
IHDR,Â_gbásRGB®ÎégAMA±üa pHYs88?'õÿ¥IDATx^ì½ ÅöÏî÷íþ÷Û½×T$$1`ÎY130b# ÂQ#%T8äs<d1¢sÆ|õÞëÝ÷_ÏÛSÓÍP}fúLO'ßßÝg'õtWÕTc=ç­·ª 3*Ub%$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmâü«$ÓÍí$×MôqÝn!þîmü 4¥B!ÿ* ü¼¹£Fë&#ú¸n7 L÷¶I~P©R1«PÈ¿Jà?oî¨äº >n£ÛÂM ÄÓ½mWb
ùWI<àçÍ5\7AÒÇmt[¸Iøcº·MòBIYêIÀÈ¿JàÜÜq!Éu }ÜF·A?¦{Û$/U*¢JÅ¥¤þ¯ 9+È¿JàÜÜq!Éu }ÜF·A?¦{Û$O¨ÿ+¢bþn1D]
xÁº¹cBë&#ú¸n7 L÷¶I!bÎ[)FÔ¥¨s)Ô1ùWI<ßÍm\7AÒÇmt[¸Iøcº·Mª(ð&0(±BX%*bÙSÆüDþUä{sG$×MôqÝn!þîm¼ M
¢)ªTR¥¤¨OÃt1Ⱥøûïü«$¨ÈÍ\7AÒÇmt[¸Iøcº·Mò6)0$¼q)ö^1Íó7Ä"ÿ* *rsÇ$×MôqÝn!þîm¼` ×SuI=
¹¹ãBë&#ú¸n7 L÷¶IÙ#ü$W
ùWI<ëÍG\7AÒÇmt[¸Iøcº·MÊOËQBþUäzsÇ$×MôqÝn!þîm²i`¹ªPÈ¿Jà\oî8äº >n£ÛÂM ÄÓ½mRÁqº¹½äº >n£ÛÂM ÄÓ½mR6L¹*n*ò¯ x ×;$¹n¤Ûè¶p ñÇto
S®
ü«$Èõæ#I® éã
etc. etc.
This is what I'm trying to do with it - with various false starts:
vm.getLabelBinaryData = function (labelId){
labelsService.getShippingLabel(labelId).then (
function success(response) {
vm.openWindowForLabels(response.data);
},
function fail(response) {
toastr.error(response.data);
}
);
};
vm.openWindowForLabels = function (responseData) {
//var b64Response = btoa(rawResponse)
var image = new Image();
image.src = 'data:image/png;base64,' + responseData;
var popupWin = window.open('', '_blank', 'width=1000,height=1000');
popupWin.document.open();
popupWin.document.write('<html><head></head><body></body></html>');
popupWin.document.body.appendChild(image);
//popupWin.document.close();
};
When I inspect the HTML, I see this:
<html><head></head><body><img src="data:image/png;base64,�PNG
Strangely, in my browser window, I see the closing img bracket, and closing body and html tags. The fact that it didn;t copy leads em to believe the data is either to long 'too long to edit', or some special character is killing it before it displays.
Either way, I get a broken image icon.
I'm stumped.
UPDATE:
I found a sample here:
https://en.wikipedia.org/wiki/Data_URI_scheme
so I plugged than in to my code:
image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
...and it indeed shows the red dot just fine.
This strongly suggests that my code is working fine and that the problems lies with parsing the data properly. (I have verified with the API dev that he is seeing a working image in POSTMAN.)

Related

How to send a local image instead of URL to Computer Vision API using React

I would like to upload local image file and extract text from it. I followed the below link and it works as expected when I pass URL. https://learn.microsoft.com/en-us/azure/developer/javascript/tutorial/static-web-app/add-computer-vision-react-app
I managed to configure for local image and get the base64 encoded dataURL of the uploaded image. But when I pass base64 encoded dataURL to Computer Vision API , it says "Input data is not a valid image" (POST 400 status code). I am getting error in the line that is shown below:
const analysis = await computerVisionClient.analyzeImage(urlToAnalyze, { visualFeatures });
The code I have included for handling local image:
const handleChange = (e) => {
var file = e.target.files[0];
var reader = new FileReader();
reader.onloadend = function()
{
setFileSelected(reader.result) // this is the base64 encoded dataurl
}
reader.readAsDataURL(file);
}
In computerVision.js file, I have changed the 'contentType' in header as below.
const computerVisionClient = new ComputerVisionClient(
new ApiKeyCredentials({ inHeader: {'Ocp-Apim-Subscription-Key': key, 'Content-Type': 'application/octet-stream'} }), endpoint);
I tried replacing client.read() with readTextInStream() as per docs in computerVision.js (please refer above link), but still throws error.
May I know why I get the error "Input data is not a valid image" ? Thanks.
Here is the link for input requirements.
There is a brand new online portal provided by Microsoft https://preview.vision.azure.com/demo/OCR
The advantage is that it will directly list your available resources so you just have to pick the right one, then you test, and there are also some samples.

How to Embed the Blob Video file in Quill JS

I am trying to append the recorded video which is blob object into quill editor but the video which is appended in the editor is not playable.
Able to see only the blob object getting printed in the quill editor. If i try to open the contents in the browser it is working fine. Any suggestions?
enter image description here
well,according to this issue,
I think you maybe need to overwrite the video module's sanitize method to make it work,for image it can work like this:
var Image = Quill.import('formats/image')
Image.sanitize = function(url) {
return url
}
so as I guess, following things maybe useful:
var Video = Quill.import('formats/video')
Video.sanitize = function(url) {
return url
}
and you may need provide blob url to make it work

Reactjs data changes, filename stays the same

I have a picture, profile.jpg on my server. When I upload a new picture, replacing picture.jpg in data but not in name (in other words, the old profile.jpg gets replaced by the new profile.jpg, but the new one is also called profile.jpg). After my promise is returned, I call forceUpdate, but this doesn't do anything unless I change the actual url (src) of the image. See my code, in which I attempted to concatenate promises in order that react would recognize that the url is changing (from the correct url, to "empty", to the correct url again):
fetch('http://localhost:3000/change_pet_pic/?petID='+this.props.pet.id+'&userID='+this.props.pet.ownerID, { method: 'POST', body: form })
.then(function(res) {
return res.json();
}).then(function(json) {
var pet = $this.props.pet;
pet.petPicture = "empty";
$this.props.pet=pet;
$this.forceUpdate();
return json.picture_url;
}).then(function(url){
var pet = $this.props.pet;
pet.petPicture = url;
$this.props.pet=pet;
$this.forceUpdate();
})
Thanks for your tips!
It seems nothing wrong with your ReactJS code instead it should be a browser cache which is causing issue by returning the old image all the time as the image url looks same.
What you can do to get rid of this is, you can access the image with different query string whenever the image is getting changed.
So the first time, you can access this with profile.jpg?v=1 and the second time, you can access it with profile.jpg?v=2 something like that.

Angular js way to download file and show loading screen using the $resource

I am using Angular js to show loading screen. It works for all the REST services call except REST service to download the file. I understand why it is not working because for download I am not making any service call using $resource; instead of that I am using normal approach to download the file therefore Angular js code doesn't have any control on start/finish the service request. I tried to use $resource to hit this REST service however I am getting the data from this service and in this case loading screen was working fine however not sure how to use this data to display to user to download in angular way. Following are required details. Please help.
Approach 1 using iframe approach:
/*Download file */
scope.downloadFile = function (fileId) {
//Show loading screen. (Somehow it is not working)
scope.loadingProjectFiles=true;
var fileDownloadURL = "/api/files/" + fileId + "/download";
downloadURL(fileDownloadURL);
//Hide loading screen
scope.loadingProjectFiles=false;
};
var $idown; // Keep it outside of the function, so it's initialized once.
var downloadURL = function (url) {
if ($idown) {
$idown.attr('src', url);
} else {
$idown = $('<iframe>', { id: 'idown', src: url }).hide().appendTo('body');
}
};
Approach 2 using $resource (Not sure how to display data on screen to download)
/*Download file */
scope.downloadFile = function (fileId) {
//Show loading screen (Here loading screen works).
scope.loadingProjectFiles=true;
//File download object
var fileDownloadObj = new DownloadFile();
//Make server call to create new File
fileDownloadObj.$get({ fileid: fileid }, function (response) {
//Q? How to use the response data to display on UI as download popup
//Hide loading screen
scope.loadingProjectFiles=false;
});
};
This is the correct pattern with the $resource service:
scope.downloadFile = function (fileId) {
//Show loading screen (Here loading screen works).
scope.loadingProjectFiles=true;
var FileResource = $resource('/api/files/:idParam', {idParam:'#id'});
//Make server call to retrieve a file
var yourFile = FileResource.$get({ id: fileId }, function () {
//Now (inside this callback) the response data is loaded inside the yourFile variable
//I know it's an ugly pattern but that's what $resource is about...
DoSomethingWithYourFile(yourFile);
//Hide loading screen
scope.loadingProjectFiles=false;
});
};
I agree with you that this is a weird pattern and is different of other APIs where the downloaded data is assigned to a parameter in a callback function, hence your confusion.
Pay attention to the names and the cases of the parameters, and look that there're two mappings involved here, one between the caller to the $resource object and the object itself, and another between this object and the url that it contructs for downloading the actual data.
Here are some idea's for the second approach, you could present the user with a link after the download has happened:
With a "data url". Probably not a good idea for large files.
With a URL like "filesystem:mydownload.zip" You'd first have to save the file with the filesystem API. You can find some inspiration on html5rocks

Opened file gets cached in titanium. Cant view replaced file content while app is running

I am facing a slight issue while editing a file.
I am saving a file (image) with a certain name on ios using the code below.
But the problem is that when i replace the image stored in a file (eg temp.jpg) the app still picks up the previous image when i open the file. However the new image can be seen in the explorer.
If i restart the app the new image appears while opening the image.
var folder = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'DocImages');
// DocImages is a folder for files
// ImageVar contains the blob for the new image from camera or gallery
// docImgModel is the model class containing the name and image path of the image
if(imageVar !== null && imageVar !== undefined){
if (docImgModel.imagePath !== null && docImgModel.imagePath !== undefined){
tempFile = Ti.Filesystem.getFile(docImgModel.imagePath);
if (tempFile.exists()) {
tempFile.deleteFile(); // deleting already existing file
}}
// in case of changing the image stored in a file(the case in which i have a
// problem) the imgFile(below) is same as docImgModel.imagePath (above)
imgFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory + 'DocImages/', filenameWithExtension); // creating a new file
// writing image to file
imgFile.write(imageVar);
Ti.API.info('new image saved');
}
}
I was wondering if titanium saves cache of the file already opened and is hence not able to show the new image.
If not, is there anything else i am doing wrong or something i could do to make it work.
I just want to show the new saved image. Is there any way to do it.
Thanks.
I haven't worked with opening files from the device, but I ran into a similar issue when trying to update data on my screen. If you are saying when you open the app and it loads the correct image comes up, then the code that you use to load the image appears correct and working. I assume that is the code you posted above. Even that appears to be a code fragment of a more complete file.
You didn't post any UI code, which is probably where your real problem is coming from. You have an object, a view of some sort I'm guessing, that is already rendered using the old image before you load the new image. So debugging, you might see the new image's data loaded in the code above, but the UI element hasn't been assigned or updated correctly.
As a test, I would suggest that you put some test code into your app that allows you to destroy your UI elements and recreate them, you will probably see the picture come up properly in that case.
According to this post: http://developer.appcelerator.com/question/31181/simple-image-refresh
Just assigning the image you loaded to the url of the image should update it. Your example code doesn't show the image object that you are attempting to update and how that communication is made from the code that is loading the image.
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
var image1 = 'image1.png';
var image2 = 'image2.png';
//
// create base UI tab and root window
//
var win1 = Titanium.UI.createWindow({
title:'Tab 1',
backgroundColor:'#fff'
});
var tab1 = Titanium.UI.createTab({
icon:'KS_nav_views.png',
title:'Tab 1',
window:win1
});
var img = Titanium.UI.createImageView({
width:100,
height:100,
top:50,
left:110,
url:image1
});
win1.add(img);
var btn = Titanium.UI.createButton({
title:'load',
width:100,
height:35,
top:50,
left:0
});
function switchImage(){
if(img.url == image1){
img.url = image2;
} else {
img.url = image1;
}
}
btn.addEventListener('click',function(){
switchImage();
});
setInterval(switchImage,3000);
win1.add(btn);
//
// add tabs
//
tabGroup.addTab(tab1);
// open tab group
tabGroup.open();

Resources