0

Getting pdf file from the API response

Hello API experts!

I would appreciate your help saving/opening a PDF file, which is the response to an API call.

This is the code of the API endpoint call inside a button:

let url := "https://testeps.e-prescription.gr/doctorapi/api/v1/me/prescriptions/************/print";
let headers := {
        Authorization: "******************",
        Accept: "application/pdf, application/xml",
        'Content-Type': "application/xml",
        'api-key': "********************"
    };
let response := do as server
        http("GET", url, headers, null)
    end;
if response.error then
    'API Response' := text(response.error)
else
    'API Response' := text(response.result)
end

And this is what I get as a response inside the 'API Response' multiline text field:

17 replies

null
    • szormpas
    • 1 yr ago
    • Reported - view

    The ability to open the pdf file from the response of this public API is crucial for the database I wish to build for my daily practice. So, I want to try every possible method before giving up on the effort.

      is the above possible using javascript or the Ninext project?

       have you encountered the above issue in any of your API applications?

         is there a way to Base64 encode the API response and then save the file in my database using a POST call to the Ninox REST API ? Could this approach be feasible?

    • Mconneen
    • 1 yr ago
    • Reported - view

    Hmm.. Nope.. But have not tried this specific use case.   I will have to scan the doc.. My first thought is to create an attachment..   The API is most likely setting a mime-type of x/pdf (or something) ..  And.. I suspect that Ninox may be treating it as text..  But those are only guesses.. 

      • szormpas
      • 1 yr ago
      • Reported - view

        seems that ChatGPT confirms your guesses!

      I uploaded a piece of the API response and received in summary the following answer:

      "The provided text appears to be a binary data representation, and based on the header information, it looks like it represents a PDF file. The %PDF-1.6 at the beginning of the data is a standard PDF file header, indicating that the binary data following it is a PDF document..........and.........Yes, the provided data is indeed in a binary format and, based on the content, it appears to be a representation of a PDF file. In the context of MIME types, the data you've shared is likely to be associated with the application/pdf MIME type, which is used to denote PDF documents."

      Therefore the question is how do we convert this binary data into a pdf file that can be opened within Ninox?

    • Mconneen
    • 1 yr ago
    • Reported - view

    Hey.. I just had a thought.. Hmm.. What if you dynamically created the URL for the API and presented the user with a URL Link?   Then.. whatever platform they are on should be able to open the URL. 

    Thoughts??

      • szormpas
      • 1 yr ago
      • Reported - view

         this sounds interesting but could you explain a bit more what you mean by "dynamically created the URL for the API and presented the user with a URL Link" or give an example?

    • Ninox developper
    • Jacques_TUR
    • 1 yr ago
    • Reported - view

    I just found a solution in JavaScript (Native JS with Ninext).
    I'm finalizing a demo app, and I'll post it by tomorrow evening.

      • szormpas
      • 1 yr ago
      • Reported - view

         this is great news, looking forward to your demo app!

    • Mconneen
    • 1 yr ago
    • Reported - view

    Well.. I could not quickly find an API that returns a PDF.. but the general idea is that your application would build a URL (this image just shows a static.. but it would be an API endpoint) . .  The end user would simply click the URL.. and let the platform use the default PDF viewer to open the link..   It’s a hack.. but might work. 
     

      • szormpas
      • 1 yr ago
      • Reported - view

         you tell me to use the url function like below?

      url(myURL, myJSON) To return a link with the content of the JSON object attached in a URL-compliant format.

      In this case what the "myURL" could be?

      • Mconneen
      • 1 yr ago
      • Reported - view

       
      I am suggesting that "myURL" can be populated into a URL field.   The user would click on that field.. So myURL would be the API end-point..    Just spit-balling.. as there is most likely access tokens and such needed.. 

      Sounds like   has a better solution to include some javaScript code.. 

      It sounds like the issue with the Ninox HTTP function is that it expects to return text .. and not binary..  I would have to play to be sure. 

    • szormpas
    • 1 yr ago
    • Reported - view

    I have also sought the help of Ninox support and    has left a possibility open by saying:

    "The only possibility I know of is a file in Base64 format, which can be stored within Ninox using the Rest API."

    But in my case the API response contains binary data, therefore I understand that if I could find a way to convert the data into a Base64 string that possibly could be a solution...

    • Ninox developper
    • Jacques_TUR
    • 1 yr ago
    • Reported - view

    The problem is indeed due to the fact that the HTTP function returns text, which distorts a portion of the content of binary files such as PDFs or images.

    Mconneen's solution, which involves creating an intermediary server that directly returns a URL, is a good solution. If you have a URL pointing directly to a PDF, it's then easy to use importFile.

    I thought about it, but it's a bit complex to implement, especially if you're not very familiar with web development.

    So, I did some more research, and after many unsuccessful attempts with complex JavaScript codes in Ninext, I often ran into the issue of cross-origin restrictions.

    And then, just before publishing one of these complex solutions that only work under certain conditions, I realized that the HTTP function can very well return data directly in base64 format instead of text. All you need to do is add {'nx-file': "base64url"} to the header. This triggers post-processing of the HTTP function, which then returns binary data in base64 format. It looks a bit like this: data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQ....

    This data format is considered a URL, and it can be passed directly to the importFile function to create a file in Ninox Script. So, there is a very simple solution directly in Ninox Script.
     

    Here is the code that's behind the "upload file from URL" button.

    'uploaded file' := null;
    var fileName := extractx(URL, "\/([^\/?#]+)[^\/]*$", "$1");
    var base64url := do as server
            http("get", URL, {
                'content-type': "application/octet-stream",
                'nx-file': "base64url"
            }, null).result
        end;
    'uploaded file' := importFile(this, text(base64url), fileName)

    The application is attached.
    Enjoy!

      • Mconneen
      • 1 yr ago
      • Reported - view

       ..    As I like to say… I often walk around the block only to go next door..  Simple solution!

      Question.. where did you find "nx-file" as a header?

      • Ninox developper
      • Jacques_TUR
      • 1 yr ago
      • Reported - view

       

      That's exactly it 😅.

      I traced Ninox's code to try to understand how responses to requests made with the http function were being handled. I came across this post-processing that is done only if nx-file is defined in the header.

      Sometimes, all it takes is to stay curious to see the door next door 😁.

      • Mconneen
      • 1 yr ago
      • Reported - view

       
      OK.. So nx-file is some Ninox specific header.   Yes.. It is both amazing.. and scary .. what you can find out using debugging tools.. LOL. 

      It will be interesting if this meets the initial use case… How to save /open a PDF that is returned from the API call.  I think it does…. but will be a multi-step process..   

    • Ninox developper
    • Jacques_TUR
    • 1 yr ago
    • Reported - view

    It seems to me that by just modifying the code like this (line 7 and 15), it should work. , could you test it and let us know?

    let url := "https://testeps.e-prescription.gr/doctorapi/api/v1/me/prescriptions/************/print";
    let headers := {
            Authorization: "******************",
            Accept: "application/pdf, application/xml",
            'Content-Type': "application/xml",
            'api-key': "********************",
            'nx-file': "base64url"
        };
    let response := do as server
            http("GET", url, headers, null)
        end;
    if response.error then
        'API Response' := text(response.error)
    else
        importFile(this, response.result);
    end
    
    • szormpas
    • 1 yr ago
    • Reported - view

    I am so happy that tears come to my eyes!

    Through the Ninox community, by studying older posts or asking for help directly, I have learned so much that I can develop my skills and improve my database daily.

    This is the second time that    and    have helped me to solve a problem, and I am grateful to you guys.

    And yes, the solution works in my case. I'm sorry that I can't share a screenshot with you due to sensitive personal data, but as Jacques TUR suggested, all I did was to add the 'nx-file’: "base64url" header to my code and then save the pdf file in an image field (Prescription:= importFile(this, text(response.result), "prescription.pdf").

    I am pleased that, οn the occasion of my case, Jacques TUR discovered a simple but well-hidden solution for storing MIME-type binary data (e.g., PDF, images, etc.) inside Ninox! I hope many users will use this valuable solution in their applications!

Content aside

  • Status Answered
  • 1 yr agoLast active
  • 17Replies
  • 5515Views
  • 4 Following