1

I'm returning a a PDF or XLSX file to the browser. I do this by setting the responseType of the ajax object that initiated the request to 'blob'. This seems to work as needed. I'm having problems figuring out a good way to pass an error string to the browser in cases where the file couldn't be created.

If I don't set any responseType on the ajax object I can read the response text as the meaninful error string I've set. This, though, means that I'm no longer able to properly read the response as a PDF or XLSX file in the cases where things proceeded properly. And, of course, I can't set the responseType of the ajax object after I've received the response.

Controller

public ActionResult GetFile() {
   // process work, set stream and success bool

   if (wasSuccessful) {
      return File(stream, "application/pdf");
   }
   else {
      return Content("a meaningful error for the UI");
   }
}

cshtml

function getFile(e, extension) {
   var xhr = new XMLHttpRequest();
   xhr.open('POST', e.value, true);
   xhr.responseType = 'blob';
   xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded");

   xhr.onload = function (ee) {
      if (this.status == 200) {
         var a = document.createElement("a");
         document.body.appendChild(a);
         a.style = "display: none";
         var blob = new Blob([this.response], { type: 'octet/stream' }), url = window.URL.createObjectURL(blob);
         a.href = url;
         a.download = "file." + extension;
         a.click();
         window.URL.revokeObjectURL(url);
      }
   };

   xhr.send($("#form").serialize());
}

Can I have my ajax expect a blob but somehow read a simple string in certain error conditions?

JoshN
  • 43
  • 9
  • Just use an if/else block based on [`responseType`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType) – Heretic Monkey Apr 01 '19 at 20:19
  • I need to set the responseType to 'blob' to be able to ingest the file properly. That means that responseType is 'blob' and that I can't switch on it. – JoshN Apr 01 '19 at 20:29
  • Your controller code shows you returning a `Content` result, which would likely have a `responseType` of "text"... If you have an error, presumably you won't have a file to ingest... – Heretic Monkey Apr 01 '19 at 20:33
  • 1
    In the case of an error, return a different HTTP status code from the server, then you can handle the error rather than trying to process a notionally "successful" response in different ways – ADyson Apr 01 '19 at 20:33
  • @HereticMonkey I can set a response type on that Content response, but if the ajax request has a responseType set to 'blob' then the responseType is 'blob' regardless of what I set the Content's response type to. And If I don't set it to blob on the ajax request I can't properly read the file. – JoshN Apr 01 '19 at 20:40
  • @ADyson I could return a status code and do something based on that, but that still leaves me unable to just show a string that I got from the server. – JoshN Apr 01 '19 at 20:41
  • I suggest going with @ADyson's strategy (you can always send text with a different status code). However, you can also [read the Blob as a string](https://stackoverflow.com/q/23024460/215552). – Heretic Monkey Apr 01 '19 at 20:45
  • "but that still leaves me unable to just show a string"...not if you **handle** the error. And the server can still return a custom value in the response body, for you to display. – ADyson Apr 01 '19 at 20:48
  • thanks you two, I'm not sure why I wasn't trying to read the blob as text...the string is right there – JoshN Apr 01 '19 at 20:54

0 Answers0