cancel
Showing results for 
Search instead for 
Did you mean: 

Handle PDF response from called URL using sendRequest in SAP MDK

geetbijlani
Participant
0 Kudos
291

Dear MDK experts,

In my iOS app build using SAP MDK. I am trying to get a PDF by calling the URL received in previous step from Adobe. When application runs on web using fetch command, it works fine and I am able to get the PDF file as the response is processed by the browser correctly. However, on iOS using sendRequest the response received is not straight forward or may be I am unable to process it correctly. 

Could you please help me with the correct way of handling the PDF response in this case. I have tried multiple ways but it just does not work.

Details: the response received is in the following format:

data = {length = 171568, bytes = 0x25504446 2d312e37 0d25e2e3 cfd30d0a ... 0a252545 4f460d0a };
    headers =     {
        "Accept-Ranges" = bytes;
        "Content-Length" = 171568;
        "Content-Type" = "application/pdf";
        Date = "Tue, 16 Jul 2024 11:08:10 GMT";
        Etag = "\\"9c3125582e1dc11f94f9304ffa12b7dd\\"";
        "Last-Modified" = "Tue, 16 Jul 2024 11:07:57 GMT";
        Server = AmazonS3;
        "Strict-Transport-Security" = "max-age=31536000; includeSubDomains; preload;";
        Via = "1.1 fde85e7daa13f95cf6b8f5fa09c62ef6.cloudfront.net (CloudFront)";
        "x-amz-cf-id" = "M0ObxiQjt3eRsE1uuDlEGzlToEH_GNozAKOeFp8LIGhkjDD4KxdIsw==";
        "x-amz-cf-pop" = "FRA56-P7";
        "x-amz-expiration" = "expiry-date=\\"Thu, 18 Jul 2024 00:00:00 GMT\\", rule-id=\\"YTNmNmJlMTktM2U4YS00NDhhLTkyNzEtNjk1NTc3NGZlMDBj\\"";
        "x-amz-id-2" = "OAvPSYiXsOkwEiKzADCWqN/AGIxCB/9tUEwqSsHNHSzr4/Az+9zDTb3ZeFqFPl5+TssIH7CyebK4DLc;
    }
}`;

here bytes contain the pdf data.

On checking the Mobile Network Trace in Mobile Services on Visual Studio, I was able to see the pdf response in the preview section. So, its on the part where we to correctly process the PDF.

 

Here is the code:

fetchUntilDone(fileRequestOptions, 5000) // Add a delay of 5 second (1000 milliseconds)
                            .then((response) => {
                              let dwnlUrl = response.asset.downloadUri;
                              let path = dwnlUrl.replace("https://dcplatformstorageservice-prod-us-east-1.s3-accelerate.amazonaws.com", "");
                              let pdfPath = "/getFinalPdf" + path;
                              let pdfActualUrl = clientAPI.getPageProxy().getControl('SectionedTable0').getControl('FC_pdfpath');
                              pdfActualUrl.setValue(path);
                            
                              const dwnldOptions = {

                                "method": "GET",
                                "responseType": "arraybuffer"
                              }
                              if (platform.isWeb == true) {
                                return fetch(dwnlUrl); //works seamlessly
                              }
                              else {
                                return clientAPI.sendRequest(pdfPath, dwnldOptions); //returns pdf but unable to process
                              }
.then((response) => {
                              

                              if (!platform.isWeb) {
                                if (response.statusCode != 200) {
                                  throw new Error('Network response was not ok ' + response.statusText);
                                }
                                // Assuming the raw data is available as a string in response.content._responseAndData
                                return response.content._responseAndData.toString();
                              }
                              else {
                                return response;
                              }


                            })

                            .then((rawData) => {
                              if (!platform.isWeb) {
                                //New approach start
                                function convertToJSON(rawData) {
                                  // Replace `=` with `:` and ensure proper formatting
                                  const formattedData = rawData
                                    .replace(/=\s*/g, ': ')
                                    .replace(/:\s*'/g, ': "')
                                    .replace(/'/g, '"')
                                    .replace(/,\s*}/g, '}')
                                    .replace(/;\s*}/g, '}')
                                    .replace(/;\s*$/g, '')
                                    .replace(/;\s*headers/g, ', headers');
                                  // Ensure keys without quotes are handled
                                  const keyValuePairs = formattedData.match(/(\w+)\s*😕g);
                                  if (keyValuePairs) {
                                    keyValuePairs.forEach(pair => {
                                      const key = pair.replace(':', '').trim();
                                      formattedData = formattedData.replace(new RegExp(`\\b${key}\\b`), `"${key}"`);
                                    });
                                  }
                                  return JSON.parse(formattedData);
                                }

                                function hexStringToByteArray(hexString) {
                                  if (!hexString) return new Uint8Array();
                                  let cleanHexString = hexString.replace(/[^0-9a-fA-F]/g, ''); // Remove any non-hex characters
                                  let byteArray = new Uint8Array(cleanHexString.length / 2);
                                  for (let i = 0; i < cleanHexString.length; i += 2) {
                                    byteArray[i / 2] = parseInt(cleanHexString.substr(i, 2), 16);
                                  }
                                  return byteArray;
                                }

                                function convertHexToBlob(hexString) {
                                  const byteArray = hexStringToByteArray(hexString);
                                  const blob = new Blob([byteArray], { type: 'application/pdf' });
                                  return blob;
                                }


                                try {
                                  const json = convertToJSON(rawData);
                                  if (json && json.data && json.data.bytes) {
                                    const hexString = json.data.bytes.replace(/\s+/g, '').replace('0x', ''); // Clean hex string
                                    const pdfBlob = convertHexToBlob(hexString);
                                    console.log(pdfBlob); // You now have the PDF blob
                                  } else {
                                    console.error('Failed to extract bytes');
                                  }
                                } catch (error) {
                                  console.error('Error converting to JSON:', error);
                                }
                              }
                              else {
                                return rawData.blob();
                              }

                            })

Kindly let me know if you see anything wrong or help me find the right way to process pdf.

 

Note: I am able to open the PDF on click of button by providing the url in the path but I need the PDF response in Blob format to save it on sharepoint online.

@bill_froelich 

Best Regards,

Geet Bijlani

View Entire Topic
cheehong_lim
Associate
Associate
0 Kudos
When using the sendRequest API on iOS to fetch a PDF document, the returned data is in the native iOS binary format. You can either call getData() to access the binary data directly or use toFile() to save it to a file. Here's an example of how to save the PDF to a temporary location:

const fileSystem = require('@nativescript/core/file-system');

let pdfPath = "/getFinalPdf" + path;
const dwnldOptions = {
method: "GET"
};

return context.sendRequest(pdfPath, dwnldOptions).then(result => {
const filePath = fileSystem.path.join(fileSystem.knownFolders.temp().path, "test.pdf");
result.content.toFile(filePath); // Save binary content to a file
});


If you need the PDF response in Blob format:

You can also use the Fetch API on the iOS platform to download a resource and handle the response as a Blob, similar to how it’s done in web environments.
geetbijlani
Participant
0 Kudos

Hi Lim,

Thanks for your reply. As my requirement is to get the PDF as BLOB, I would refer to your suggestion

"If you need the PDF response in Blob format:
You can also use the Fetch API on the iOS platform to download a resource and handle the response as a Blob, similar to how it’s done in web environments."
 
I would like to inform you that I have already tried this rather this was my first approach but the Fetch API specifically in this case does not work correctly on iOS platform specifically. The execution stops after the fetch call on iOS but the same thing works on Web. I cannot analyse/debug the Fetch call as the same is not recorded by Mobile Network Trace, only sendRequest is recorded.
So, kindly guide me if the Fetch for this simple GET needs to be called in a different way for iOS or is there a way to do sendRequest and get the response as BLOB.
 
Looking forward for your valuable inputs.
 
Best Regards,
Geet