I am currently developing an Android App using Cordova, and my goal is to open and display a file (PDF or image) that is retrieved from the server as Base64-encoded binary data. Despite going through various posts on this topic within this platform, none of the suggested solutions seem to work for me. Here are more details regarding my situation:
Specifically, the server sends a JSON-file to the app, which includes a string containing the base64-encoded content of a PDF file among other things. My objective is to convert this data back into the original PDF format and present it to the user.
If this were a regular web page, I could easily embed my base64 data into a data-URL, set this as the href of an anchor tag, and add a download attribute. Alternatively, I could bundle all the data into a blob and create an object URL for it first before displaying.
In Cordova, these methods do not yield the desired results. Clicking the <a>
element does not trigger any action. Here's what I have tried so far:
- Utilizing the file plugin, I managed to write the binary data to a file on the device. While I confirmed successful downloading via a terminal, the file was saved in an app-private directory inaccessible through normal means such as the file explorer.
- Access to the user's "downloads" folder is restricted by the file system.
- Using window.open with the file path as the argument and "_system" as the target fails to produce any outcome. There are no errors reported but nothing happens either. Changing the target to "_blank" resulted in an ACCESS_DENIED error.
- The use of cordova.InAppBrowser led to similar outcomes as window.open.
- When attempting to utilize the file-opener2 plugin, the compile process failed as the plugin requires an android4 toolchain while I am targeting android 9 and above.
- A similar issue arose when trying to employ the document-viewer plugin for PDFs exclusively; compilation proved unsuccessful.
- Directly passing the data-URI to window.open or cordova.InAppBrowser considerably delayed loading and eventually displayed an error stating the desired page couldn't be loaded.
The test PDF file I'm working with converts to roughly 17kb after encoding into base64. While this exceeds the specified limit for data-URIs, Chrome functions without issues when handling this size. Additionally, even a significantly shorter URI behaves in the same manner.
My preferred approach would involve downloading the file and then prompting the user's standard browser to open the file automatically. This method would eliminate MIME type concerns and ensure consistency with the user's expectations. Alternatively, if this doesn't prove viable, I would settle for downloading the file into a system-wide directory and allowing the user to open it manually. Although not ideal, I would accept this compromise.
Finally, if there exists a suitable plugin or alternative solution catering specifically to PDFs, I can devise a separate strategy for images (e.g., incorporating a new <img> tag into the app and assigning the appropriate URI).
Your input on overcoming this challenge would be greatly appreciated. Below is the code segment I presently employ for file downloads:
Thank you for your consideration.
var filePath = cordova.file.externalDataDirectory;
var fileName = "someFileName.pdf";
var mime = "application/pdf";
var dataBlob = /* blob containing the PDF binary data */
function writeFile(fileEntry, dataBlob) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function() {
console.log("Successful file write...");
readFile(fileEntry);
};
fileWriter.onerror = function (e) {
console.log("Failed file write: " + e.toString());
};
fileWriter.write(dataBlob);
});
}
window.resolveLocalFileSystemURL(
filePath,
function onResolveSuccess (dirEntry) {
dirEntry.getFile(
fileName,
{ create: true },
function onGetFileSuccess (file) (
writeFile(file, dataBlob);
window.open(file.toURL(), "_system"); // This line does not achieve the intended result, and the reason remains unclear.
}
);
}
);