How to save Base64 String to file and view it using Flutter - file

I need to download and view file (if possible, for Image, PDF, etc) using Flutter.
My problem is, the file that I want to download is Base64 String.
How can I achieve that using Flutter??

Following is the code snippet to decode base64 string and save it as a file on the local device. please note in terms of viewing files, image and pdf would require different libraries.
Future<String> _createFileFromString() async {
final encodedStr = "put base64 encoded string here";
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File(
"$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + ".pdf");
await file.writeAsBytes(bytes);
return file.path;
}

Google Chrome does not let open tab with Url base64 encode, like "data:application/pdf;base64,JVBERi0xLjQKJeLj..." with javascript, so you can not open url with url_launcher, but you can download file.
Here is my code:
import 'dart:html' as html;
...
Future<void> downloadFile() {
final urlString = "data:application/pdf;base64,JVBERi0xLjQKJeLj...";
html.AnchorElement anchorElement = html.AnchorElement(href:urlString);
anchorElement.download = urlString;
anchorElement.click();
}

Related

Is it possible to directly upload images captured by camera to Firebase Storage?

I'm using React.js to create an application that would take a photo and upload it to Firebase Storage. I am using the react-webcam library, which uses this command to take a photo:
const ImageSrc = webcamRef.current.getScreenshot();
This is how I tried uploading the photo to Storage:
storage.ref(`/images`).put(imageSrc)
.on("state_changed" , alert("success") , alert)
However, the file that is uploaded is undefined (no photo).
I tried to construct an URL of the photo using blob:
const imageUrl = window.URL.createObjectURL(new Blob(webcamRef.current.getScreenshot()))
But I get this error: >Failed to construct 'Blob': The provided value cannot be converted to a sequence.
In the library it is stated that getScreenshot - Returns a base64 encoded string of the current webcam image. So, I tried to use the atob command, but I get the error: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
Does anyone know how I could upload the image to Firebase Storage? Any help would be appreciated!
Instead of blob, try using putString() command like this:
const task = firebase.storage().ref(`/images`).putString(imageSrc, 'data_url')
As explained in the doc, if you want to upload from a Base64url formatted string, you need to call the putString() method as follows (example from the doc):
var message = '5b6p5Y-344GX44G-44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64url').then((snapshot) => {
console.log('Uploaded a base64url string!');
});
In your case, since getScreenshot() returns a base64 encoded string, it would be something like:
const imageSrc = webcamRef.current.getScreenshot();
storage.ref(`/images`).putString(imageSrc, 'imgBase64')
.on("state_changed" , alert("success") , alert)

Flutter Web: Downloading file from URL without opening it

I want users to be able to download files uploaded by them. The problem is, certein files (like .pdf) are getting open in the browser, not downloaded. Is there any solution to just download a file in Flutter Web without opening it in the web browser?
Code that I'm using:
final anchor = AnchorElement(
href: url)
..setAttribute("download", fileName)
..click();
Following this answer, you can generate url from a string or from a list of int (bytes of file). Here is a short snipper that should work (from the answer above):
import 'dart:convert';
import 'dart:html' as html; // or package:universal_html/prefer_universal/html.dart
final text = 'this is the text file';
// prepare
final bytes = utf8.encode(text);
final blob = html.Blob([bytes]);
final url = html.Url.createObjectUrlFromBlob(blob);
final anchor = html.document.createElement('a') as html.AnchorElement
..href = url
..style.display = 'none'
..download = 'some_name.txt';
html.document.body.children.add(anchor);
// download
anchor.click();
// cleanup
html.document.body.children.remove(anchor);
html.Url.revokeObjectUrl(url);
Also, universal_html package is very handy to use html on all Flutter platforms. Using dart:html in a Flutter mobile app will make compiling fail.

Rename file saved to the file system with angular 2

I want to save a blob downloaded from a server onto the file system, so i use
window.open( window.URL.createObjectURL(myBlob));
to save it. But when i do that, then the saved file gets a completly jumbled random name.
Is there any way to give the saved file my own name?
EDIT:
Server side looks like this (Spring Data REST controller):
#RequestMapping(value = "/downloadFile/{fileName}", method = RequestMethod.GET)
public void downloadFile(#PathVariable(value="fileName") String fileName, HttpServletResponse response) throws IOException {
File file = getMyFile(fileName)
response.addHeader("Content-Disposition", "attachment; filename="+file.getName());
response.setContentType(Files.probeContentType(file.toPath()));
response.setContentLengthLong(file.length());
response.getOutputStream().write(FileUtils.readFileToByteArray(file));
}
I've been searching for a similar answer myself and found several possibilities to save a downloaded file.
In your case you can use the download attribute of the <a> element:
. You can dynamically add this element when for instance a button is clicked, and programmatically perform the click event.
var a = document.createElement("a"),
fileURL = URL.createObjectURL(blob);
a.style = "display:none";
a.href = fileURL;
a.download = fileName;
window.document.body.appendChild(a);
a.click();
window.document.body.removeChild(a);
URL.revokeObjectURL(fileURL);
The download atrribute only has recent support: http://www.w3schools.com/tags/att_a_download.asp
For older versions of IE, use
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveOrOpenBlob(blob, fileName);
}

Firebase storage uploading broken image

I have a cropped image using this cropper. It is returning a base64 version of the cropped image.
I am trying to convert that base64 image to a blob or a file to be able to upload it to firebase storage using the code below.
var imageBase64 = $scope.cropper.croppedImage.split(',')[1];
var blob = new Blob([imageBase64], {type: 'image/png'});
var file = new File([imageBase64], 'imageFileName2.png', {type: 'image/png'});
when I tried to print file it has created an acutal File object that looks like this.
{
lastModified:1471604365544,
lastModifiedDate:"Fri Aug 19 2016 18:59:25 GMT+0800 (PHT)",
name:"imageFileName2.png",
size:228808,
type:"image/png",
webkitRelativePath:""
}
The File is being uploaded successfully though, but the result is broken. The preview on the firebase storage dashboard just looks like this (it never stops loading, and when I tried to download it, I got a broken image) :
To prove that my base64 image is not broken, here's a base64 pic of my cat Akasha, you can preview it in this base64 viewer.
In the 3.3.0 JS client, you can just upload a base64 string (docs)!
var imageBase64 = $scope.cropper.croppedImage.split(',')[1];
ref.putString(imageBase64, 'base64').then(function(snapshot) {
console.log('Uploaded a base64 string!');
});
The Blob and File APIs both take a UInt8Array, which the base64 string isn't, so you were basically creating an array that contained a single item, which was the base64 string, which wasn't a valid blob. Use the above upload to solve the problem.

Angular how to upload the file string, but NOT the physical file itself

I have an angular app that generate a pdf string and want to upload it (encoded uri, or raw data option).
I know that for a physical file, you can do the upload, but what about the pdf string generated within the app? is there a way to upload such?
My code is something like this:
var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
var str = doc.output('datauristring'); // this will be uri encoded string
var raw = doc.output();
var myForm = new FormData();
myForm.append('file', <what should go here??>);
//...
// POST myForm to backend

Resources