Я хочу скачать файл PDF в приложении Cordova. Я получаю строку base64, которая является тем PDF.
Я попробовал следующий код, используя cordova-plugin-file и cordova-plugin-file-opener2:
openPDF(invoice) {
this.saveAndOpenPdf(invoice['base64'], 'invoice.pdf');
}
saveAndOpenPdf(pdf: string, filename: string) {
const load = this.loadingCtrl.create({
content: this.translate.instant("app.loading"),
dismissOnPageChange: true
});
load.present();
var writeDirectory = this.platform.is('ios') ? this.file.dataDirectory : this.file.externalRootDirectory;
console.log(writeDirectory);
var self = this;
this.checkPermissions()
.then(() => {
var res = this.b64toBlob(pdf, 'aplication/pdf', 512);
console.log(res);
( < any > window).resolveLocalFileSystemURL(writeDirectory, function(dir) {
console.log("Access to the directory granted succesfully");
dir.getFile(filename, {
create: true
}, function(file) {
console.log("File created succesfully.");
file.createWriter(function(fileWriter) {
console.log("Writing content to file");
fileWriter.write(res);
self.opener.open(writeDirectory + filename, 'application/pdf').then(() => {
load.dismiss();
})
.catch((err) => {
console.error(err);
console.log('Error opening pdf file');
load.dismiss();
});
}, function() {
load.dismiss();
alert('Unable to save file in path ' + writeDirectory);
});
});
});
}).catch((error) => {
load.dismiss();
console.log(error);
});
}
b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {
type: contentType
});
return blob;
}
Кажется, это работает хорошо, но когда открыватель пытается открыть PDF-файл, он терпит неудачу, и размер PDF-файла равен 0B. ( ТОЛЬКО В АНДРОИДЕ )
Что я делаю не так?
PD: это пример кода: https://ourcodeworld.com/articles/read/230/how-to-save-a-pdf-from-a-base64-string-on-the-device-with-cordova
ДОБАВЛЕНО:
Также я попробовал решение, объясненное в этом посте: https://stackoverflow.com/a/49137874/8228843
В этих случаях в android, только в android, функция file.writeFile ничего не делала. Обещание не сработало, и код then () не был выполнен, равно как и код catch (). Важно отметить, что нет ошибок ни в консоли, ни в logcat.
Код решения в посте пояснил:
saveAndOpenPdf(pdf: string, filename: string) {
const writeDirectory = this.platform.is('ios') ? this.file.dataDirectory : this.file.externalDataDirectory;
this.file.writeFile(writeDirectory, filename, this.convertBase64ToBlob(pdf, 'data:application/pdf;base64'), {replace: true})
.then(() => {
this.loading.dismiss();
this.opener.open(writeDirectory + filename, 'application/pdf')
.catch(() => {
console.log('Error opening pdf file');
this.loading.dismiss();
});
})
.catch(() => {
console.error('Error writing pdf file');
this.loading.dismiss();
});
}
convertBaseb64ToBlob(b64Data, contentType): Blob {
contentType = contentType || '';
const sliceSize = 512;
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
const byteCharacters = window.atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
return new Blob(byteArrays, {type: contentType});
}