cesarvr / pdf-generator

Cordova plugin to generate pdf in the client-side
MIT License
106 stars 62 forks source link

Is there a way to save the pdf to a file in Download folder? #82

Closed jfoclpf closed 6 years ago

jfoclpf commented 6 years ago

Hi

Is there a way to save the pdf to a file in the Downloads folder? Shall I use type 'base64' ?

jfoclpf commented 6 years ago

Have you tested this? https://ourcodeworld.com/articles/read/230/how-to-save-a-pdf-from-a-base64-string-on-the-device-with-cordova

jfoclpf commented 6 years ago

I do confirm that such code works :)

You may want to add this code to your project, to save a pdf file to the Downloads folder

you would use like this

var fileName = "pdfile.pdf";

var options = {
    documentSize: 'A4',
    type: 'base64'                
};

var pdfhtml = '<html><body style="font-size:120%">This is the pdf content</body></html>';

pdf.fromData(pdfhtml , options)
    .then(function(base64){               
        // To define the type of the Blob
        var contentType = "application/pdf";

        // if cordova.file is not available use instead :
        // var folderpath = "file:///storage/emulated/0/Download/";
        var folderpath = cordova.file.externalRootDirectory + "Download/";
        savebase64AsPDF(folderpath, fileName, base64, contentType);          
    })  
    .catch((err)=>console.err(err));

you will need these two functions. Due to javascript functions hoisting you can declare them afterwards as here

/**
 * Convert a base64 string in a Blob according to the data and contentType.
 * 
 * @param b64Data {String} Pure base64 string without contentType
 * @param contentType {String} the content type of the file i.e (application/pdf - text/plain)
 * @param sliceSize {Int} SliceSize to process the byteCharacters
 * @see http://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript
 * @return Blob
 */
function 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;
}

/**
 * Create a PDF file according to its database64 content only.
 * 
 * @param folderpath {String} The folder where the file will be created
 * @param filename {String} The name of the file that will be created
 * @param content {Base64 String} Important : The content can't contain the following string (data:application/pdf;base64). Only the base64 string is expected.
 */
function savebase64AsPDF(folderpath,filename,content,contentType){
    // Convert the base64 string in a Blob
    var DataBlob = b64toBlob(content,contentType);

    console.log("Starting to write the file :3");

    window.resolveLocalFileSystemURL(folderpath, 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(DataBlob);
            }, function(){
                alert('Unable to save file in path '+ folderpath);
            });
        });
    });
}
cesarvr commented 6 years ago

I think is a nice practice to inform your users what your app is trying to do, I think that the share option is more appropriate for cases where you need to save files, as the user has full control over the generated document.

Of course if displaying the UI to the user is not an option, I think your snippet get the job done, if you feel kind please share in the how tos via PR.

Thanks!

jfoclpf commented 6 years ago

Yes, my point is that the "share" was opening the printing menu and my purpose was merely to directly download the file into the Downlods folder, being transparent to the user. Of course, the app needs permission to such folder.

Ok. I will check that

Thanks

On Sun, 20 May 2018, 15:59 Cesar Valdez, notifications@github.com wrote:

I think is a nice practice to inform your users what your app is trying to do, I think that the share option is more appropriate for cases where you need to save files, as the user has full control over the generated document.

Of course if displaying the UI to the user is not an option, I think your snippet get the job done, if you feel kind please share in the how tos https://github.com/cesarvr/pdf-generator#howto via PR.

Thanks!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cesarvr/pdf-generator/issues/82#issuecomment-390485069, or mute the thread https://github.com/notifications/unsubscribe-auth/ADzODbE3TLVtH7mfrWt0jH9zIqvBu5uwks5t0XawgaJpZM4UGAqd .

jfoclpf commented 6 years ago

I made a pull request as you suggested you may want, if you find appropriate, create another method toFile(folder, filename) or use type: file Thanks

cesarvr commented 6 years ago

Thank You for the contribution. I'll take a look how to implement that functionality.

jfoclpf commented 6 years ago

You're welcomed

On Sun, 20 May 2018, 20:53 Cesar Valdez, notifications@github.com wrote:

Thank You for the contribution. I'll take a look how to implement that functionality.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cesarvr/pdf-generator/issues/82#issuecomment-390503070, or mute the thread https://github.com/notifications/unsubscribe-auth/ADzODUnRUF1k0g60shnbjjlaekXfDicaks5t0bu8gaJpZM4UGAqd .