How to download a file when a django function is called by javascript instead of navigation to the url?












0















I have a page where several buttons process different functions like sending a sms (via API), sends a file by email, or downloads a PDF file. Button actions dont use forms, but uses ajax requests via javascript.



I used to create a pdf file using javascript (jspdf), but have written code which generates a pdf file by python on the server. Now I need to allow download when the button is clicked.



Server code snippet:



with NamedTemporaryFile(mode='w+b') as temp:
from django.http import FileResponse
doc = SimpleDocTemplate(temp.name, pagesize=A4, rightMargin=20, leftMargin=20, topMargin=20, bottomMargin=20, allowSplitting=1, title="Prescription", author="MyOPIP.com")
doc.build(elements)
print(f'Generated {temp.name}')
return FileResponse(open(temp.name, 'rb'), content_type='application/pdf')


The above code is supposed to download a pdf file, if called by navigating to the url.



On my javascript side, I tried to determine what I'm receiving:



$.ajax({
url: `/clinic/${cliniclabel}/prescription/download/patient/${patient_id}`,
dataType: "html",
data: data,
type: 'POST',
success: function (data) {
console.log("Received data from server..type is ", typeof(data))
console.log(data)
}
});


And I get:



Received data from server..type is  string
%PDF-1.4
%���� ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R /F2 5 0 R
>>
endobj
2 0 obj....


Apparently django sends this as a file stream. How can I get the file downloaded to the user when the response is processed by javascript?










share|improve this question





























    0















    I have a page where several buttons process different functions like sending a sms (via API), sends a file by email, or downloads a PDF file. Button actions dont use forms, but uses ajax requests via javascript.



    I used to create a pdf file using javascript (jspdf), but have written code which generates a pdf file by python on the server. Now I need to allow download when the button is clicked.



    Server code snippet:



    with NamedTemporaryFile(mode='w+b') as temp:
    from django.http import FileResponse
    doc = SimpleDocTemplate(temp.name, pagesize=A4, rightMargin=20, leftMargin=20, topMargin=20, bottomMargin=20, allowSplitting=1, title="Prescription", author="MyOPIP.com")
    doc.build(elements)
    print(f'Generated {temp.name}')
    return FileResponse(open(temp.name, 'rb'), content_type='application/pdf')


    The above code is supposed to download a pdf file, if called by navigating to the url.



    On my javascript side, I tried to determine what I'm receiving:



    $.ajax({
    url: `/clinic/${cliniclabel}/prescription/download/patient/${patient_id}`,
    dataType: "html",
    data: data,
    type: 'POST',
    success: function (data) {
    console.log("Received data from server..type is ", typeof(data))
    console.log(data)
    }
    });


    And I get:



    Received data from server..type is  string
    %PDF-1.4
    %���� ReportLab Generated PDF document http://www.reportlab.com
    1 0 obj
    <<
    /F1 2 0 R /F2 5 0 R
    >>
    endobj
    2 0 obj....


    Apparently django sends this as a file stream. How can I get the file downloaded to the user when the response is processed by javascript?










    share|improve this question



























      0












      0








      0








      I have a page where several buttons process different functions like sending a sms (via API), sends a file by email, or downloads a PDF file. Button actions dont use forms, but uses ajax requests via javascript.



      I used to create a pdf file using javascript (jspdf), but have written code which generates a pdf file by python on the server. Now I need to allow download when the button is clicked.



      Server code snippet:



      with NamedTemporaryFile(mode='w+b') as temp:
      from django.http import FileResponse
      doc = SimpleDocTemplate(temp.name, pagesize=A4, rightMargin=20, leftMargin=20, topMargin=20, bottomMargin=20, allowSplitting=1, title="Prescription", author="MyOPIP.com")
      doc.build(elements)
      print(f'Generated {temp.name}')
      return FileResponse(open(temp.name, 'rb'), content_type='application/pdf')


      The above code is supposed to download a pdf file, if called by navigating to the url.



      On my javascript side, I tried to determine what I'm receiving:



      $.ajax({
      url: `/clinic/${cliniclabel}/prescription/download/patient/${patient_id}`,
      dataType: "html",
      data: data,
      type: 'POST',
      success: function (data) {
      console.log("Received data from server..type is ", typeof(data))
      console.log(data)
      }
      });


      And I get:



      Received data from server..type is  string
      %PDF-1.4
      %���� ReportLab Generated PDF document http://www.reportlab.com
      1 0 obj
      <<
      /F1 2 0 R /F2 5 0 R
      >>
      endobj
      2 0 obj....


      Apparently django sends this as a file stream. How can I get the file downloaded to the user when the response is processed by javascript?










      share|improve this question
















      I have a page where several buttons process different functions like sending a sms (via API), sends a file by email, or downloads a PDF file. Button actions dont use forms, but uses ajax requests via javascript.



      I used to create a pdf file using javascript (jspdf), but have written code which generates a pdf file by python on the server. Now I need to allow download when the button is clicked.



      Server code snippet:



      with NamedTemporaryFile(mode='w+b') as temp:
      from django.http import FileResponse
      doc = SimpleDocTemplate(temp.name, pagesize=A4, rightMargin=20, leftMargin=20, topMargin=20, bottomMargin=20, allowSplitting=1, title="Prescription", author="MyOPIP.com")
      doc.build(elements)
      print(f'Generated {temp.name}')
      return FileResponse(open(temp.name, 'rb'), content_type='application/pdf')


      The above code is supposed to download a pdf file, if called by navigating to the url.



      On my javascript side, I tried to determine what I'm receiving:



      $.ajax({
      url: `/clinic/${cliniclabel}/prescription/download/patient/${patient_id}`,
      dataType: "html",
      data: data,
      type: 'POST',
      success: function (data) {
      console.log("Received data from server..type is ", typeof(data))
      console.log(data)
      }
      });


      And I get:



      Received data from server..type is  string
      %PDF-1.4
      %���� ReportLab Generated PDF document http://www.reportlab.com
      1 0 obj
      <<
      /F1 2 0 R /F2 5 0 R
      >>
      endobj
      2 0 obj....


      Apparently django sends this as a file stream. How can I get the file downloaded to the user when the response is processed by javascript?







      javascript python ajax django






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 17 '18 at 5:15







      Joel G Mathew

















      asked Nov 17 '18 at 5:07









      Joel G MathewJoel G Mathew

      2,02292745




      2,02292745
























          1 Answer
          1






          active

          oldest

          votes


















          0














          It is impossible to do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns).



          That being said, the work around would be to set the "src" of an anchor tag to the url for the file download and trigger a click on it.



          Note: You'll have to change your function method from POST to GET




          • Change the "button" to an "a" link and have src="#" in the html.

          • Add an ng-click to it to trigger a JS function

          • In the JS function, do not call event.PreventDefault(); and then update the "src" of the "a" tag.

          • Once function is done executing, then it'll trigger the normal click on the <a> tag anyway (with the source updated)


          I haven't tested the above; so if that doesn't work, move the try the following:




          • Keep the button as is

          • Add a new hidden <a> tag with src="#"

          • In the JS function, update the src of the <a> tag and trigger click on the element.


          Comment under here if you have any questions.






          share|improve this answer
























          • Why not just add a window.open javascript method, and navigate to the new url?

            – Joel G Mathew
            Nov 17 '18 at 11:00











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53348420%2fhow-to-download-a-file-when-a-django-function-is-called-by-javascript-instead-of%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          It is impossible to do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns).



          That being said, the work around would be to set the "src" of an anchor tag to the url for the file download and trigger a click on it.



          Note: You'll have to change your function method from POST to GET




          • Change the "button" to an "a" link and have src="#" in the html.

          • Add an ng-click to it to trigger a JS function

          • In the JS function, do not call event.PreventDefault(); and then update the "src" of the "a" tag.

          • Once function is done executing, then it'll trigger the normal click on the <a> tag anyway (with the source updated)


          I haven't tested the above; so if that doesn't work, move the try the following:




          • Keep the button as is

          • Add a new hidden <a> tag with src="#"

          • In the JS function, update the src of the <a> tag and trigger click on the element.


          Comment under here if you have any questions.






          share|improve this answer
























          • Why not just add a window.open javascript method, and navigate to the new url?

            – Joel G Mathew
            Nov 17 '18 at 11:00
















          0














          It is impossible to do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns).



          That being said, the work around would be to set the "src" of an anchor tag to the url for the file download and trigger a click on it.



          Note: You'll have to change your function method from POST to GET




          • Change the "button" to an "a" link and have src="#" in the html.

          • Add an ng-click to it to trigger a JS function

          • In the JS function, do not call event.PreventDefault(); and then update the "src" of the "a" tag.

          • Once function is done executing, then it'll trigger the normal click on the <a> tag anyway (with the source updated)


          I haven't tested the above; so if that doesn't work, move the try the following:




          • Keep the button as is

          • Add a new hidden <a> tag with src="#"

          • In the JS function, update the src of the <a> tag and trigger click on the element.


          Comment under here if you have any questions.






          share|improve this answer
























          • Why not just add a window.open javascript method, and navigate to the new url?

            – Joel G Mathew
            Nov 17 '18 at 11:00














          0












          0








          0







          It is impossible to do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns).



          That being said, the work around would be to set the "src" of an anchor tag to the url for the file download and trigger a click on it.



          Note: You'll have to change your function method from POST to GET




          • Change the "button" to an "a" link and have src="#" in the html.

          • Add an ng-click to it to trigger a JS function

          • In the JS function, do not call event.PreventDefault(); and then update the "src" of the "a" tag.

          • Once function is done executing, then it'll trigger the normal click on the <a> tag anyway (with the source updated)


          I haven't tested the above; so if that doesn't work, move the try the following:




          • Keep the button as is

          • Add a new hidden <a> tag with src="#"

          • In the JS function, update the src of the <a> tag and trigger click on the element.


          Comment under here if you have any questions.






          share|improve this answer













          It is impossible to do it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns).



          That being said, the work around would be to set the "src" of an anchor tag to the url for the file download and trigger a click on it.



          Note: You'll have to change your function method from POST to GET




          • Change the "button" to an "a" link and have src="#" in the html.

          • Add an ng-click to it to trigger a JS function

          • In the JS function, do not call event.PreventDefault(); and then update the "src" of the "a" tag.

          • Once function is done executing, then it'll trigger the normal click on the <a> tag anyway (with the source updated)


          I haven't tested the above; so if that doesn't work, move the try the following:




          • Keep the button as is

          • Add a new hidden <a> tag with src="#"

          • In the JS function, update the src of the <a> tag and trigger click on the element.


          Comment under here if you have any questions.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 17 '18 at 7:38









          Pranay MajmundarPranay Majmundar

          1649




          1649













          • Why not just add a window.open javascript method, and navigate to the new url?

            – Joel G Mathew
            Nov 17 '18 at 11:00



















          • Why not just add a window.open javascript method, and navigate to the new url?

            – Joel G Mathew
            Nov 17 '18 at 11:00

















          Why not just add a window.open javascript method, and navigate to the new url?

          – Joel G Mathew
          Nov 17 '18 at 11:00





          Why not just add a window.open javascript method, and navigate to the new url?

          – Joel G Mathew
          Nov 17 '18 at 11:00


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53348420%2fhow-to-download-a-file-when-a-django-function-is-called-by-javascript-instead-of%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()