How to preview a base64 PDF with ionic capacitor - ionic-framework

I am trying to open and preview a PDF from a capacitor application.
Here is my code :
const { Browser } = Plugins;
let base64Pdf = "";
var contentType = "application/pdf";
var dataBlob = this.b64toBlob(base64Pdf, contentType);
await Browser.open({ url: URL.createObjectURL(dataBlob) }).then(() => {
console.log("PDF OK");
}).catch(err => {
console.log(err);
})
This is working great on web, but does not work on iOS. I get an error saying that the URL is invalid. I also tried to use
window.open(URL.createObjectURL(dataBlob), '_blank');
and
window.open(URL.createObjectURL(dataBlob), '_system');
But none of these work. I do not get any error output.
When using self, the PDF is opening well, but since it opens inside the webview, there is no more control and the user is stuck :
window.open(URL.createObjectURL(dataBlob), '_system');
Thanks in advance for any help

Related

FILE_URI path for Camera not working on IONIC 4

When using the Cameara to take a picture with destinationType: this.camera.DestinationType.FILE_URI, the resulting URL will not work to display the image. For example, when attempting to take a photo like this:
this.camera.getPicture(options).then((url) => {
// Load Image
this.imagePath = url;
}, (err) => {
console.log(err);
});
Attempting to display it as <img [src]="imagePath" > will result in an error (file not found).
The problem here is that the URL is in the file:///storage... path instead of the correct one based on localhost.
In previous versions of Ionic, this would be solved by using normalizeURL. This will not work on Ionic 4 (or at least I could not make it work).
To solve this issue, you will need to use convertFileSrc():
import {WebView} from '#ionic-native/ionic-webview/ngx';
...
this.camera.getPicture(options).then((url) => {
// Load Image
this.imagePath = this.webview.convertFileSrc(url);
}, (err) => {
console.log(err);
});
Now the image URL will be in the appropriate http://localhost:8080/_file_/storage... format and will load correctly.
See WKWebView - Ionic Docs for more information.
In my case, the following code works with me
const downloadFileURL = 'file:///...';
// Convert a `file://` URL to a URL that is compatible with the local web server in the Web View plugin.
const displayedImg = (<any>window).Ionic.WebView.convertFileSrc(downloadFileURL);
In case some gots here looking for the answer on ionic4, check this out
"Not allowed to load local resource" for Local image from Remote page in PhoneGap Build
and look for the answer from #Alok Singh that's how I got it working on ionic4 and even works with livereload
UPDATE december 2021:
You have to install the new Ionic Webview
RUN:
ionic cordova plugin add cordova-plugin-ionic-webview
npm install #awesome-cordova-plugins/ionic-webview
Import it in app.module and your page where you wanna use it:
import { WebView } from '#awesome-cordova-plugins/ionic-webview/ngx';
image = "";
constructor(private webview: WebView){}
Then this will work:
this.camera.getPicture(options).then((imageData) => {
this.image = this.webview.convertFileSrc(imageData)
}, (err) => {
// Handle error
});
And show it in the HTML page:
<img [src]="image" alt="">

How to download mongo collections as file using iron-router (and ground-db)? [duplicate]

I'm playing with the idea of making a completely JavaScript-based zip/unzip utility that anyone can access from a browser. They can just drag their zip directly into the browser and it'll let them download all the files within. They can also create new zip files by dragging individual files in.
I know it'd be better to do it serverside, but this project is just for a bit of fun.
Dragging files into the browser should be easy enough if I take advantage of the various methods available. (Gmail style)
Encoding/decoding should hopefully be fine. I've seen some as3 zip libraries so I'm sure I should be fine with that.
My issue is downloading the files at the end.
window.location = 'data:jpg/image;base64,/9j/4AAQSkZJR....'
this works fine in Firefox but not in Chrome.
I can embed the files as images just fine in chrome using <img src="data:jpg/image;ba.." />, but the files won't necessarily be images. They could be any format.
Can anyone think of another solution or some kind of workaround?
If you also want to give a suggested name to the file (instead of the default 'download') you can use the following in Chrome, Firefox and some IE versions:
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
And the following example shows it's use:
downloadURI("data:text/html,HelloWorld!", "helloWorld.txt");
function download(dataurl, filename) {
const link = document.createElement("a");
link.href = dataurl;
link.download = filename;
link.click();
}
download("data:text/html,HelloWorld!", "helloWorld.txt");
or:
function download(url, filename) {
fetch(url)
.then(response => response.blob())
.then(blob => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
})
.catch(console.error);
}
download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");
Ideas:
Try a <a href="data:...." target="_blank"> (Untested)
Use downloadify instead of data URLs (would work for IE as well)
Want to share my experience and help someone stuck on the downloads not working in Firefox and updated answer to 2014.
The below snippet will work in both firefox and chrome and it will accept a filename:
// Construct the <a> element
var link = document.createElement("a");
link.download = thefilename;
// Construct the uri
var uri = 'data:text/csv;charset=utf-8;base64,' + someb64data
link.href = uri;
document.body.appendChild(link);
link.click();
// Cleanup the DOM
document.body.removeChild(link);
Here is a pure JavaScript solution I tested working in Firefox and Chrome but not in Internet Explorer:
function downloadDataUrlFromJavascript(filename, dataUrl) {
// Construct the 'a' element
var link = document.createElement("a");
link.download = filename;
link.target = "_blank";
// Construct the URI
link.href = dataUrl;
document.body.appendChild(link);
link.click();
// Cleanup the DOM
document.body.removeChild(link);
delete link;
}
Cross-browser solutions found up until now:
downloadify -> Requires Flash
databounce -> Tested in IE 10 and 11, and doesn't work for me. Requires a servlet and some customization. (Incorrectly detects navigator. I had to set IE in compatibility mode to test, default charset in servlet, JavaScript options object with correct servlet path for absolute paths...) For non-IE browsers, it opens the file in the same window.
download.js -> http://danml.com/download.html Another library similar but not tested. Claims to be pure JavaScript, not requiring servlet nor Flash, but doesn't work on IE <= 9.
There are several solutions but they depend on HTML5 and haven't been implemented completely in some browsers yet. Examples below were tested in Chrome and Firefox (partly works).
Canvas example with save to file support. Just set your document.location.href to the data URI.
Anchor download example. It uses <a href="your-data-uri" download="filename.txt"> to specify file name.
Combining answers from #owencm and #Chazt3n, this function will allow download of text from IE11, Firefox, and Chrome. (Sorry, I don't have access to Safari or Opera, but please add a comment if you try and it works.)
initiate_user_download = function(file_name, mime_type, text) {
// Anything but IE works here
if (undefined === window.navigator.msSaveOrOpenBlob) {
var e = document.createElement('a');
var href = 'data:' + mime_type + ';charset=utf-8,' + encodeURIComponent(text);
e.setAttribute('href', href);
e.setAttribute('download', file_name);
document.body.appendChild(e);
e.click();
document.body.removeChild(e);
}
// IE-specific code
else {
var charCodeArr = new Array(text.length);
for (var i = 0; i < text.length; ++i) {
var charCode = text.charCodeAt(i);
charCodeArr[i] = charCode;
}
var blob = new Blob([new Uint8Array(charCodeArr)], {type: mime_type});
window.navigator.msSaveOrOpenBlob(blob, file_name);
}
}
// Example:
initiate_user_download('data.csv', 'text/csv', 'Sample,Data,Here\n1,2,3\n');
This can be solved 100% entirely with HTML alone. Just set the href attribute to "data:(mimetypeheader),(url)". For instance...
<a
href="data:video/mp4,http://www.example.com/video.mp4"
target="_blank"
download="video.mp4"
>Download Video</a>
Working example: JSFiddle Demo.
Because we use a Data URL, we are allowed to set the mimetype which indicates the type of data to download. Documentation:
Data URLs are composed of four parts: a prefix (data:), a MIME type indicating the type of data, an optional base64 token if non-textual, and the data itself. (Source: MDN Web Docs: Data URLs.)
Components:
<a ...> : The link tag.
href="data:video/mp4,http://www.example.com/video.mp4" : Here we are setting the link to the a data: with a header preconfigured to video/mp4. This is followed by the header mimetype. I.E., for a .txt file, it would would be text/plain. And then a comma separates it from the link we want to download.
target="_blank" : This indicates a new tab should be opened, it's not essential, but it helps guide the browser to the desired behavior.
download: This is the name of the file you're downloading.
If you only need to actually have a download action, like if you bind it to some button that will generate the URL on the fly when clicked (in Vue or React for example), you can do something as easy as this:
const link = document.createElement('a')
link.href = url
link.click()
In my case, the file is already properly named but you can set it thanks to filename if needed.
For anyone having issues in IE:
dataURItoBlob = function(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: 'image/png'});
}
var blob = dataURItoBlob(uri);
window.navigator.msSaveOrOpenBlob(blob, "my-image.png");
This code was originally provided by #Yetti on this answer (separate question).
Your problem essentially boils down to "not all browsers will support this".
You could try a workaround and serve the unzipped files from a Flash object, but then you'd lose the JS-only purity (anyway, I'm not sure whether you currently can "drag files into browser" without some sort of Flash workaround - is that a HTML5 feature maybe?)
Coming late to the party, if you'd like to use a function without using the DOM, here it goes, since the DOM might not even be available for whatever reason.
It should be applicable in any Browser which has the fetch API.
Just test it here:
// declare the function
function downloadAsDataURL (url) {
return new Promise((resolve, reject) => {
fetch(url)
.then(res => res.blob())
.then(blob => {
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onloadend = () => resolve(reader.result)
reader.onerror = err => reject(err)
})
.catch(err => reject(err))
})
}
// simply use it like this
downloadAsDataURL ('https://cdn-icons-png.flaticon.com/512/3404/3404134.png')
.then((res) => {
console.log(res)
})
.catch((err) => {
console.error(err)
})
export const downloadAs = async (url: string, name: string) => {
const blob = await axios.get(url, {
headers: {
'Content-Type': 'application/octet-stream',
},
responseType: 'blob',
});
const a = document.createElement('a');
const href = window.URL.createObjectURL(blob.data);
a.href = href;
a.download = name;
a.click();
};
You can use a clean code solution, inform your url in a constant, and set it as param of open method instead in object window.
const url = "file url here"
window.open(url)

How to fetch and navigate to url provided by API using TypeScript

I have a website manager that will return to me a different url for the server that my client should connect too.
So what I would like to do in my typescript function is resolve the first url, read the text, and then open that in a new window. Right now I can only open website manager window with the bellow code.
var aWindow = window.open("http://azureredirect.net/home/workspace/" + this.workspace.id, "Window", "");
if (aWindow) {
aWindow.focus();
}
What I really want is something like the following but the WebClient line does not work(this is the C# version of what I would do)
var url = WebClient.open("http://azurejupyterredirect.net/home/workspace/" + this.workspace.id").toString();
var aWindow = window.open(url, "JuPy", "");
if (aWindow) {
aWindow.focus();
}
here's an example of how you could do this:
$(document).ready(function() {
var workspaceId = '2';
$.ajax('http://azurejupyterredirect.net/home/workspace/' + workspaceId)
.then(
function(url) {
window.open(url);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Why this link's test doesn't work?

I write a test for a link with Protractor(using Pattern Page Object), but it always gave an error. So I decide to see what was going on and I write this one:
test.spec.js
it('It should redirect to Google.de', function(){
var logo = angularPage.logo3;
angularPage.clickLink(logo);
browser.getCurrentUrl().then(function (url) {
console.log('---> url:'+url);
});
});
login.page.js
this.navigate = function(ptor) {
browser.get(browser.baseUrl);
ptor = protractor.getInstance();
ptor.waitForAngular();
}
this.clickLink = function(link){
link.click();
var ptor;
this.navigate(ptor);
}
And what I got was the link didn't redirect me to another web page. I think is weird because the link actually works when I click on it. Anyone know what that can be happening?
Thanks.
My problem was that when you try to get current URL you can get it with two ways:
Supports AngularJS
var logo = angularPage.logoH3;
angularPage.clickLink(logo);
browser.getCurrentUrl().then(function (url) {
console.log('---> URL: '+url);
});
No Supports AngularJS
var logo = angularPage.logoH3;
angularPage.clickLink(logo);
browser.driver.getCurrentUrl().then(function (url) {
console.log('---> URL: '+url);
});
So login.page.js stays finally like this
login.page.js
this.clickLink = function(link){
link.click();
}
Thanks for your helping and your time ;)

How to use POST method in Appcelerator Titanium for iPhone?

I have used the POST method in Titanium for Android app and it is working fine. But in iPhoen Simulator it shows a blank array in the server side to be posted.
var req = Titanium.Network.createHTTPClient({
timeout : 15000
});
req.open("POST", url);
req.onload = function(e) {
//YOUR CODE HERE
}
req.onerror = function(e) {
//YOUR CODE HERE
}
req.send(params);
If, server requires json format of data than you can use req.send(JSON.stringify(params)) otherwise you can send it simply.