Convert base64 string to PDF in AngularJS - angularjs

I am unable to open a base64 string as pdf in angular application if the file size is more than say 10mb. The browser crashes with a page saying "AW, SNAP". The base64 string i.e. "base64content" already has the metadata at the start and looks something like this:
data:application/pdf;base64,JVBERi0xLjQK...DUKJSVFT0YK
I am using below way to open the base64 string as a PDF in new tab:
$window.open(base64content);

Try with
window.open('data:application/pdf;base64,' + base64content);

This happened because the base64 string was too big for the browser to interpret. This is because the pdf was heavy(more than 2mb) the approx max limit of browser. The solution was to use blob based approach.

Related

How To Upload A Large File (>6MB) To SalesForce Through A Lightning Component Using Apex Aura Methods

I am aiming to take a file a user attaches through an Lightning Component and create a document object containing the data.
So far I have overcome the request size limits by chunking the data being uploaded into 1MB chunks. When the Apex Aura method receives these chunks of data it will either create a new document (if it is the first chunk), or will retrieve the existing document and add the new chunk to the end.
Data is received Base64 encoded, and then decoded server-side.
As the document data is stored as a Blob, the original file contents will be read as a String, and then appended with the chunk received. The new contents are then converted back into a Blob to be stored within the ContentVersion object.
The problem I'm having is that strings in Apex have a maximum length of 6,000,000 or so. Whenever the file size exceeds 6MB, this limit is hit during the concatenation, and will cause the file upload to halt.
I have attempted to avoid this limit by converting the Blob to a String only when necessary for the concatenation (as suggested here https://developer.salesforce.com/forums/?id=906F00000008w9hIAA) but this hasn't worked. I'm guessing it was patched because it's still technically allocating a string larger then the limit.
Code's really simple when appending so far:
ContentVersion originalDocument = [SELECT Id, VersionData FROM ContentVersion WHERE Id =: <existing_file_id> LIMIT 1];
Blob originalData = originalDocument.VersionData;
Blob appendedData = EncodingUtil.base64Decode(<base_64_data_input>);
Blob newData = Blob.valueOf(originalData.toString() + appendedData.toString());
originalDocument.VersionData = newData;
You will have hard time with it.
You could try offloading the concatenation to asynchronous process (#future/Queueable/Schedulable/Batchable), they'll have 12MB RAM instead of 6. Could buy you some time.
You could try cheating by embedding an iframe (Visualforce or lightning:container tag? Or maybe a "canvas app") that would grab your file and do some manual JavaScript magic calling normal REST API for document upload: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm (last code snippet is about multiple documents). Maybe jsforce?
Can you upload it somewhere else (SharePoint? Heroku?) and have that system call into SF to push them (no Apex = no heap size limit). Or even look "Files Connect" up.
Can you send an email with attachments? Crude but if you write custom Email-to-Case handler class you'll have 36 MB of RAM.
You wrote "we needed multiple files to be uploaded and the multi-file-upload component provided doesn't support all extensions". That may be caused by these:
In Experience Builder sites, the file size limits and types allowed follow the settings determined by site file moderation.
lightning-file-upload doesn't support uploading multiple files at once on Android devices.
if the Don't allow HTML uploads as attachments or document records security setting is enabled for your organization, the file uploader cannot be used to upload files with the following file extensions: .htm, .html, .htt, .htx, .mhtm, .mhtml, .shtm, .shtml, .acgi, .svg.

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.

Why does the Google App Engine python Blob care about what is stored in it

I have been struggling with some very basic understanding of how google app engine store data
I have defined a class defining a client profile as such :
class ClientProfile(ndb.Model):
nickname = ndb.StringProperty(required=True)
photo = ndb.BlobProperty()
uuid = ndb.StringProperty(required = True)
I retrieve an image data only uploading image.src via a POST using jquery.ajax(...)
The data are properly sent to Google app engine and I can assign them to a variable with
imagesrc = self.request.get('photosrcbase64')
The data content is something looking like :
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...
So fare so good, the data is an image/png and the encoding is Base64, but should I care if it end in a Blob ?
Now if I try to put the data in the photo Blob
with for example :
clientprofile.photo = imagesrc I get a Bad Value Error, in this case :
BadValueError: Expected str, got
u'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAA
I tried all kind of combinations using different solutions and get back all kind of BadValue or type errors.
My question are :
1) Why does the Blob care, if it is a binary storage, I should be able to dump in it anything without having to interpret it and/or convert it, so is a Blob really a Binary/Raw storage and why does it care about how things are stored in it ?
2) I have started having problems with this 2 years ago when still using db instead of ndb, I found a solution that I did not understand by stripping out the MIME information at the beginning of the data string, decoding the string Base64 and using db.Blob(...) to convert my string to a Blob. the problem is that db.Blob() does not seem to exist in ndb so I can't do this any more.
I am convinced that I am missing something fundamental in the way informations are exchanged between google app engine and the browser and thank you in advance for a mind clearing answer
A BlobProperty is meant to be binary data. The str type in Python is fully equivalent to a byte string since the only characters allowed are
[chr(byte_value) for byte_value in range(2**8)]
So before storing the value from self.request.get('photosrcbase64'), which is of type unicode, you'll need to cast to type str.
You can do this either by directly doing so
imagesrc = str(self.request.get('photosrcbase64'))
or first trying to decode to ascii.

golang: emailing an image stored as a Google Appengine blobstore blob

I'm trying to read a JPEG file stored in the GAE blobstore back into a byte array using the following code:
info,_ := blobstore.Stat(context,appengine.BlobKey(request.FormValue("blobkey")))
image := make([]byte,info.Size)
reader := blobstore.NewReader(context,appengine.BlobKey(request.FormValue("blobkey")))
n,nerr := reader.Read(image)
The image is stored correctly i.e. it can be served using blobstore.Send(...).
And the above code sort of works (in that it does read back the blob data) but it converts any 0x0a byte into a 0x0d 0x0a pair (i.e. LF into CR LF).
Is there a way in Go to work around this behaviour (without writing a filter to convert 0x0d0a back to 0x0a) ?
EDIT:
It turns out the problem is not with Blobstore.Reader at all, but with the attachment encoding in mail.py on the dev appserver.
The mail attachment handling on the dev appserver does not correctly encode image data. If the attachment data is known to be binary, a partial workaround is to add the line:
encoders.encode_base64(mime_attachment)
after the line
mime_attachment.set_payload(attachment.data())
in the file
google/appengine/api/mail.py
Using a MIMEImage attachment for an image content type would be a better solution but causes a 'LazyImporter object is not callable' error.

GAE Blobstore: ImagesService.getServingUrl() gives me smaller images

I'm uploading some images to GAE's Blobstore. Upload goes succesfully and when i see the images in GAE console i can see that they're stored in the expected size and resolution.
According to this site, to get a URL to the uploaded image i can use this:
BlobKey blobKey = (BlobKey) blobs.get("image");
ImagesService imagesService = ImagesServiceFactory.getImagesService();
String imageUrl = imagesService.getServingUrl(blobKey);
The resulting URL points to a smaller version of the uploaded images (in size and quality). How can i get a URL to the full size image stored in Blobstore?
you can append =s0 parameter after the url to get full sized image.

Resources