0

I am making an app that uploads images to an UploadCollection (SAPUI5) with instantUpload=false. I have extended the UploadCollection control to process these image files before the upload process begins. In this redefinition I have merged all these images in a PDF using the library "jsPDF".

The problem arrives when uploading the PDF file in a "standard" way, it means, using the standard "sendFiles" function of the UploadCollection. This method needs that these files are of type: "File". What I have is a base64 string. This means I need to use the "new File()" constructor.

With this base64 string I have created a blob and with this blob I have created a File. I achieve uploading the file, but when I try to open it, the file is unreadable. I believe that the creation process of the file is wrong.

I followed several tutorials and could not resolve my problem.

I know that in Ajax I can upload the blob, but I don't want to use Ajax as I need to use ODataModel because of best practices of my company.

If I parse the base64 string into a PDF file I can see the PDF right, so the problem is not the base64 string generation.

If I use Chrome, the generation of the file works but I can see that the name property contains the blob and the localURL contains the name, as if there was a missorder in the parameters. Is like if Chrome doesn't follow this API: https://www.w3.org/TR/FileAPI/#dfn-file

If I use Firefox the properties are correct, but when I download the file I have the same problem. The file can't be displayed.

I have tried so many things that I can't list them all here.

/**
* Function that converts string to blob
* @param {String} sBase64Data String with the base64 info
* @param {String} sContentType mimeType of the data: application/pdf
* @returns {Blob} Blob for the new File()
*/ 
_b64toBlob: function (sBase64Data, sContentType) {
    var aByteCharacters = atob(sBase64Data);
    var aByteArrays = [];
    var iSliceSize = 512;
    // var iSliceSize = 1;

    for (var offset = 0; offset < aByteCharacters.length; offset += iSliceSize) {
        var slice = aByteCharacters.slice(offset, offset + iSliceSize);

        var aByteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
            aByteNumbers[i] = slice.charCodeAt(i);
        }

        var aByteArray = new Uint8Array(aByteNumbers);
        aByteArrays.push(aByteArray);
    }

    var blob = new Blob(aByteArrays, {
        type: sContentType
    });
    return blob;
},

//In other part of the code....
var sContentType = "application/pdf";
var sPDFBase64 = btoa(doc.output());
var oBlob = this._b64toBlob(sPDFBase64, sContentType);
var fFile = new File([oBlob], sFileName, { type: sContentType });
aFiles.push(fFile);
this._sendFilesWithXHR(aFiles);

David F.
  • 1
  • 2
  • If you check my code you will see that my function is precisely that one :) I have seen that thread previosly, but what I am doing is not downloading the file but uploading it. So I need to convert to File and the continue with the normal process of this control. i.e.: I need to create a "File". – David F. Apr 04 '19 at 08:00
  • Just a thought (I was generating png from client svg in past) - you'd want to pass base64 directly to the server and transform it to the file there, so you won't need to deal with different browsers. – extempl Apr 04 '19 at 08:25
  • Have you seen this solution: https://stackoverflow.com/questions/34436133/pdf-is-blank-when-downloading-using-javascript/45669785#45669785 ? – extempl Apr 04 '19 at 08:46
  • The problem is that the SAPUI5 control that I am using to upload via ODataModel needs a File to upload. I have tested another aproach to the problem: var oBlob = doc.output("blob"); var fFile = new File([oBlob], sFileName, { type: sContentType }); Doesn't work either. I am thinking of a possible workaround with FileReader or something like that. – David F. Apr 04 '19 at 08:47
  • @extempl I have read that solution previously. Again, that example doesn't create a File. It downloads the blob. I have tested it and yes, I can download the blob and the PDF and it is correct, but what I want is to **instantiate a File()**. Thanks for your advice anyway :) – David F. Apr 04 '19 at 08:56
  • Uhm, yes, it creates blob, which you could use then to create a file. The thing, that it should work already ,while your code doesn't, as I understand. – extempl Apr 04 '19 at 08:57
  • So use that solution to get a blob, remove all logic related to download link, then create a File with the blob you get and you should be ok – extempl Apr 04 '19 at 08:58
  • In my code I use this instruction which apparently is not working properly: ```var fFile = new File([oBlob], sFileName, { type: sContentType });``` I want to test a few things because I am starting to think that the "standard method" of the UploadCollection is not working properly for some reason. – David F. Apr 04 '19 at 09:30
  • Try to use without contentType: `new File([blob], "filename")` – extempl Apr 04 '19 at 09:36
  • SOLVED. I haven't fixed the problem with Chrome, but I have tried to upload directly the blob and it worked. Not the most orthodox solution, but it worked. Thanks to those that have helped :) – David F. Apr 05 '19 at 07:45

0 Answers0