0

I have an HTTP POST REST endpoint that consumes an image and returns an HTML document with pixel data from the image. The HTTP response includes the header Content-Disposition: attachment; filename=Pixels.html so that the browser would prompt for downloading.

I would like to have an HTML/JavaScript (not jQuery) app that

  1. allows me to browse and pick an image (e.g., <input id="fid" name="fid" type="file" />
  2. on clicking a link post the image data to the endpoint and let me download the HTML content to the disk (e.g., <p onclick="javascript: getPixels()">Get Pixels</p>).

How do I go about doing this? I tried the following code:

  function getPixels() {
     var input = document.getElementById("fid");
     if (input.files && input.files[0]) {
        if (typeof (FileReader) != "undefined") {
           var reader = new FileReader();
           reader.onload = function (e) {
              var imgData = e.target.result;
              var postUrl = "./GetPixelsService.svc/image";
              var xhr = new XMLHttpRequest();
              xhr.open("POST", postUrl);
              xhr.setRequestHeader("Content-Type", "image/png");
              //xhr.onreadystatechange = function () {
              //   if (xhr.readyState === 4) {
              //      var res_display = document.getElementById("results");
              //      res_display.srcdoc = xhr.responseText;
              //   }
              //}
              xhr.send(imgData);
           };
           reader.readAsArrayBuffer(input.files[0]);
        }
     }
  }

The following is the HTML blurb that calls the above function.

  <p>
     Upload the image here:
  </p>
  <input id="fid" name="fid" type="file" />
  <!--<button type="submit" onclick="javascript: getPixels()">Get Pixels</button>-->
  <p onclick="javascript: getPixels()">Get Pixels</p>
  <p />
  <hr />
  <p>
     <img id="img2check" src="" alt="" />
  </p>
  <p />
  <iframe id="results" style="width: 100%; border: 0; height: 400px;" src="javascript:;">
     Your browser does not support iframes.
  </iframe>

I am able to pick the response and display it in an iframe, but unable to get the browser to download the content.

Appreciate your help. I have looked at the relevant questions on StackOverflow, but none has helped so far.

Thanks in advance.

pengu1n
  • 471
  • 6
  • 15

2 Answers2

1

You can't force the client browser to prompt a save dialog with an XMLHttpRequest.

What you can do are followings:

1: Check this answer of mine to another question similar to this: How to get pdf file via javascript ajax

2: Generate the file on server or create a get type request handler and give link to it with download attribute. http://www.w3schools.com/TAgs/att_a_download.asp

3: Use 3rd party apps like Downloadify: https://github.com/dcneiner/Downloadify

4: There is another way using Blob, which i haven't tried yet, in here: Browser/HTML Force download of image from src="data:image/jpeg;base64...". This post is about a base64 image, but i think it's worth to try with an html file.

Community
  • 1
  • 1
er-han
  • 1,859
  • 12
  • 20
  • Thank you. I tried creating a URL via Blob, but that did not work: the contents of the URL got dumped to the page instead. I will take another look. – pengu1n Jan 19 '17 at 18:07
  • The server-side is REST, so what it is expecting is just the image binary. That's why I didn't go through the forms approach (which would encode the image binary). Is there a way to send just the image binary via form? – pengu1n Jan 19 '17 at 18:09
  • Thank you. A combination of (2) and (4) does the magic. I will post the whole solution as an answer for the benefit of others. Thanks again ... – pengu1n Jan 19 '17 at 20:46
1

Thanks to er-han, the following code achieves the goal.

  <!DOCTYPE html>
  <html>
  <head>
     <meta charset="utf-8" />
     <title></title>
  </head>
  <body>
     <script type="text/javascript">
        function getPixels() {
           showImage();
           var input = document.getElementById("fid");
           if (input.files && input.files[0]) {
              if (typeof (FileReader) != "undefined") {
                 var reader = new FileReader();
                 reader.onload = function (e) {
                    var imgData = e.target.result;
                    var postUrl = "./SimpleService.svc/image";
                    var xhr = new XMLHttpRequest();
                    xhr.open("POST", postUrl);
                    xhr.setRequestHeader("Content-Type", "image/png");
                    xhr.onreadystatechange = function () {
                       if (xhr.readyState === 4) {
                          var res_url = URL.createObjectURL(new Blob([xhr.responseText]));
                          var lnk = document.getElementById("dlink");
                          lnk.href = res_url;
                          lnk.style.display = "block";
                       }
                    }
                    xhr.send(imgData);
                 };
                 reader.readAsArrayBuffer(input.files[0]);
              }
           }
        }

        function showImage() {
           var input = document.getElementById("fid");
           if (input.files && input.files[0]) {
              if (typeof (FileReader) != "undefined") {
                 var reader = new FileReader();
                 reader.onload = function (e) {
                    var img_display = document.getElementById("img2check");
                    img_display.src = e.target.result;
                 };
                 reader.readAsDataURL(input.files[0]);
              }
           }
        }
     </script>

     <p>
        Upload the image here:
     </p>
     <input id="fid" name="fid" type="file" />
     <p/>
     <button type="submit" onclick="javascript: getPixels()">Upload</button>
     <p />
     <hr />
     <p>
        <img id="img2check" src="" alt="" />
     </p>
     <p />
     <p>
        <a id="dlink" href="#" download="Data.html" style="display: none;">Download data</a>
     </p>
  </body>
  </html>
pengu1n
  • 471
  • 6
  • 15
  • I hadn't time to work on it sorry, but i am glad you did it. I am sure i am going to need this proper answer in the future :) – er-han Jan 20 '17 at 06:42
  • Appreciate your help. Wouldn't have been able to do it without it. Thanks again! :-) – pengu1n Jan 20 '17 at 10:50