Save base64 string as PDF at client side with JavaScript
You can create an anchor like the one showed below to download the base64 pdf:
<a download=pdfTitle href=pdfData title='Download pdf document' />
where pdfData is your base64 encoded pdf like "data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nO1cyY4ktxG911fUWUC3kjsTaBTQ1Ytg32QN4IPgk23JMDQ2LB/0+2YsZAQzmZk1PSPIEB..."
android - download base64 encoded pdf file and open it
Found a thread online and solved it this way: https://www.py4u.net/discuss/614761
Add provider_paths.xml to xml resource folder
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
In your manifest add a FileProvider:
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
Prepare to download files to any directory your app owns, such as getFilesDir(), getExternalFilesDir(), getCacheDir() or getExternalCacheDir().
val privateDir = context.getFilesDir()
Download file taking its progress into account (DIY):
val downloadedFile = myFancyMethodToDownloadToAnyDir(url, privateDir, fileName)
Copy it to Downloads folder:
private val DOWNLOAD_DIR = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val finalUri : Uri? = copyFileToDownloads(context, downloadedFile)
fun copyFileToDownloads(context: Context, downloadedFile: File): Uri? {
val resolver = context.contentResolver
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, getName(downloadedFile))
put(MediaStore.MediaColumns.MIME_TYPE, getMimeType(downloadedFile))
put(MediaStore.MediaColumns.SIZE, getFileSize(downloadedFile))
}
resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
} else {
val authority = "${context.packageName}.provider"
val destinyFile = File(DOWNLOAD_DIR, getName(downloadedFile))
FileProvider.getUriForFile(context, authority, destinyFile)
}?.also { downloadedUri ->
resolver.openOutputStream(downloadedUri).use { outputStream ->
val brr = ByteArray(1024)
var len: Int
val bufferedInputStream = BufferedInputStream(FileInputStream(downloadedFile.absoluteFile))
while ((bufferedInputStream.read(brr, 0, brr.size).also { len = it }) != -1) {
outputStream?.write(brr, 0, len)
}
outputStream?.flush()
bufferedInputStream.close()
}
}
Once in download folder you can open file from app like this:
val authority = "${context.packageName}.provider"
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(finalUri, getMimeTypeForUri(finalUri))
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
} else {
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
try {
context.startActivity(Intent.createChooser(intent, chooseAppToOpenWith))
} catch (e: Exception) {
Toast.makeText(context, "Error opening file", Toast.LENGTH_LONG).show()
}
//Kitkat or above
fun getMimeTypeForUri(context: Context, finalUri: Uri) : String =
DocumentFile.fromSingleUri(context, finalUri)?.type ?: "application/octet-stream"
//Just in case this is for Android 4.3 or below
fun getMimeTypeForFile(finalFile: File) : String =
DocumentFile.fromFile(it)?.type ?: "application/octet-stream"
how to download base64 string as pdf in IE version 11 & same for mozilla firefox
You can check following code it's working for IE 11 and other browsers.
function downloadFile(pdfBase64, fileName) {
// IE doesn't allow using a blob object directly as link href
// instead it is necessary to use msSaveOrOpenBlob
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
var byteCharacters = atob(pdfBase64);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: 'application/pdf' });
window.navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
// For Other Browsers
const linkSource = 'data:application/pdf;base64,' + pdfBase64;
const link = document.createElement('a');
link.href = linkSource;
link.download = fileName;
document.body.appendChild(link);
link.click();
link.remove();
window.addEventListener("focus", function () {
URL.revokeObjectURL(link.href);
}, { once: true });}
Download PDF from Base64 string
The example here seems helpful: http://php.net/manual/en/function.readfile.php
In your case:
<?php
$decoded = base64_decode($base64);
$file = 'invoice.pdf';
file_put_contents($file, $decoded);
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
This should force the download to occur.
Base64 String to pdf JavaScript React Native then download
If you just want to show the pdf in react-native.The react-native-pdf package can do the job.Use a source obj like this.
const source = {uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."};
If you want to download base64 to pdf file, it's also simple.
var RNFetchBlob = require('react-native-fetch-blob').default;
const DocumentDir = RNFetchBlob.fs.dirs.DocumentDir;
let pdfLocation = DocumentDir + '/' + 'test.pdf';
RNFetchBlob.fs.writeFile(pdfLocation, pdf_base64Str, 'base64');
export async function downloadFile(url){
let binary = await getPdfBinary(url);
const base64Str = base64_encode(binary);
const DocumentDir = RNFetchBlob.fs.dirs.DocumentDir;
let pdfLocation = DocumentDir + '/' + 'test.pdf';
RNFetchBlob.fs.writeFile(pdfLocation, base64Str, 'base64');
}
I'm sorry I didn't notice that you are using expo. As I have never written codes about the file system part in the expo. After a lot try, it finally works. But only for android. I think you may hope the pdf file should be saved to an external storage path so the user can see it in the file app. But for ios, It is hard to reach that. A possible way is to use the share dialog. If you just want to save the pdf file to the document folder in the app(not see by the user), FileSystem.writeAsStringAsync is enough!Hope this is helpful!
import * as FileSystem from 'expo-file-system';
import { Platform } from 'react-native';
async function getPdfBinary(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer"; // get the binary
xhr.setRequestHeader('content-type', 'application/json');
xhr.onload = function (event) {
var arrayBuffer = xhr.response;
var byteArray = new Uint8Array(arrayBuffer);
var len = byteArray.byteLength;
var binary = ""
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(byteArray[i]);
}
resolve(binary);
}
xhr.send();
})
}
function base64_encode(str) {
var c1, c2, c3;
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var i = 0,
len = str.length,
string = '';
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt((c1 & 0x3) << 4);
string += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
string += base64EncodeChars.charAt((c2 & 0xF) << 2);
string += "=";
break;
}
c3 = str.charCodeAt(i++);
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
string += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
string += base64EncodeChars.charAt(c3 & 0x3F)
}
return string
}
const downloadForAos = async (pdfBase64Str) => {
const folder = FileSystem.StorageAccessFramework.getUriForDirectoryInRoot("test");
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync(folder);
if (!permissions.granted) return;
let filePath = await FileSystem.StorageAccessFramework.createFileAsync(permissions.directoryUri, "test.pdf", "application/pdf");
// let filePath = "content://com.android.externalstorage.documents/tree/primary%3Atest/document/primary%3Atest%2Ftest.txt";
console.log(pdfBase64Str, "====");
try {
await FileSystem.StorageAccessFramework.writeAsStringAsync(filePath, pdfBase64Str, { encoding: FileSystem.EncodingType.Base64 });
alert("download success!")
} catch (err) {
console.log(err);
}
}
const downloadForIos = async () => {
alert("try do it by yourself")
}
export async function downloadPdf(url) {
let binary = await getPdfBinary(url);
console.log(binary, "=====")
const base64Str = base64_encode(binary);
if (Platform.OS === "ios") {
downloadForIos(base64Str);
} else {
downloadForAos(base64Str);
}
}
Node.js - Download locally docx or pdf encoded as base64 string
I've solved with this solution:
const express = require("express");
const atob = require("atob");
const router = express.Router();
const fs = require('fs');
router.post("/evaluate", function(req, res) {
var oResume = req.body.resume;
var sMimeType = oResume.mimeType;
var sFileExtension = oResume.fileExtension;
var sBase64 = oResume.content.replace(/(\r\n|\n|\r)/gm, "");
var sBinaryString = atob(sBase64);
var len = sBinaryString.length;
var aBytes = new Uint8Array(len);
for (var i=0; i<len; i++) {
aBytes[i] = sBinaryString.charCodeAt(i);
}
var blob = Buffer.from(aBytes.buffer);
fs.writeFile("cvs/out."+sFileExtension, blob, function(err) {
console.log(err);
});
res.status(200).send("OK");
});
module.exports = router;
Related Topics
Redirect to Url After Form Submit in React
Expected Linebreaks to Be 'Lf' But Found 'Crlf' Linebreak-Style
Change Specific Button Text on Click Inside Ngfor
How to Save an Image to Localstorage and Display It on the Next Page
How to Display the Entire Object in Console in React Native
How to Reduce Vendor/Script Bundle.Js in Angular 5
Executing Nodejs Script File in PHP Using Exec()
How Insert JavaScript into Vue File
Comparing Two Json Arrays and Get Not Matching Values
Violation Long Running JavaScript Task Took Xx Ms
Mobile Safari Sometimes Does Not Trigger the Click Event
Make Discord Bot Send Picture With Message With Nodejs
Slick Carousel - Force Slides to Have the Same Height
Download Image as File in Typescript
Keep Order of Objects Inside a Json String After They Are Parsed
How to Wait Until 2 $Http Requests End in Angularjs