-1

I am trying to display a PDF after a successful AJAX call to my controller. I needed to modify the original way I was doing it to be able to handle multiple PDFs to return a single one.

The old way:

var uri = '../api/Controller/' + string1 + "," + string2 + "," + string3;
var src = '../web/printViewer.html?file=' + encodeURIComponent(uri);
window.open(src, "_blank");

So I have tried to keep the functionality of that with an AJAX call that looks like this:

$.ajax({
    type: 'get',
    url: '../api/Controller',
    contentType: 'application/json; charset=utf-8',
    data: { thing1: item, thing2: item2 },
    datatype: 'json',
    success: function (result) {
        // no bueno D:
        // but I get back a proper PDF every time
    },
    error: function () {
        toastr.error('Error creating print.');
    }
});

and for the C# controller:

[HttpGet]
public HttpResponseMessage Get(string thing1, string thing2) //thing2 will be a string[] eventually, once I am able to get 2-3 pdfs working
{
    byte[] data = response.PDFBytes[0] == null ? new byte[0] : response.PDFBytes[0];
    int length = response.PDFBytes[0] == null ? 0 : response.PDFBytes[0].Length;

    var stream = new MemoryStream(data, 0, length, true, true);

    result.Content = new ByteArrayContent(stream.GetBuffer());

    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "CheckedOutItems.pdf"
    };

    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
}

The first thing I tried to do was to just turn the entire thing into one big string, but it was getting far too long with only a few PDFs. I know the controller is returning a solid PDF, but I cannot seem to display it in the printViewer window.

Thanks in advance!!

EDIT:

I am not trying to download the file. I just wish to open it in a new window so the user can print it. Someone has suggested the same article twice now where the developer is trying to download the PDF. That is not what I am after.

Corey Whaley
  • 66
  • 3
  • 11
  • You want just download or show it? What is printViewer window? – teo van kot May 25 '17 at 13:37
  • @teovankot I want to show it. PrintViewer is just a different window that automatically pulls up the print dialogue for the user. – Corey Whaley May 25 '17 at 13:54
  • Well then i can only say DO NOT DOWNLOAD FILES WITH AJAX. That's really tricky thing so it's better just use old way. For more info [check this](https://stackoverflow.com/q/4545311/1849444). – teo van kot May 25 '17 at 13:57
  • @teovankot I am not trying to download the PDF, but I will look into that article to see if anything assists with me displaying and then printing it. – Corey Whaley May 25 '17 at 13:59
  • Possible duplicate of [Download a file by jQuery.Ajax](https://stackoverflow.com/questions/4545311/download-a-file-by-jquery-ajax) – teo van kot May 25 '17 at 14:03
  • @teovankot I am failing to see how this is a duplicate when we are trying to achieve two separate goals.. The answers suggested in that thread do not assist me as I do NOT want to download the resulting PDF from the AJAX call – Corey Whaley May 25 '17 at 14:13

2 Answers2

2

What I ended up having to do in this scenario was saving the file to disk, and on a on a success to the AJAX call I would then go grab the PDF from Disk and display that, being careful to then delete the PDF from disk afterwards. I didn't want to save it at all, but I didn't see another way.

The reason I came to this solution was that the new window was actually opening before it was going to the controller to get the image, but when I did the ajax call THEN tried to open it in a new window, it wouldn't play nice, which resulted in another call to the server.

$.ajax({
    type: 'get',
    url: '../api/Controller',
    contentType: 'application/json; charset=utf-8',
    data: { thing1: item, thing2: item2 },
    datatype: 'json',
    success: function (result) {
        var uri = '../api/GetPDFOffDisk/ + pdfName;
        var src = '../web/printViewer.html?file=' + encodeURIComponent(uri);
        window.open(src, "_blank");
    },
    error: function () {
        toastr.error('Error creating print.');
    }
});

And in the controller that was receiving the pdf from the service call (implemented down after I create the MemoryStream):

using (Filestream fs = new File.OpenWrite(_path))
{
    stream.WriteTo(fs);
    file.Dispose();
}

In the new controller to grab and return the PDF from disk:

if (File.Exists(_path))
{
    using (FileStream file = System.IO.File.OpenRead(_path))
    {
        var data = File.ReadAllBytes(_path);
        int length = data.Length;
        MemoryStream ms = new MemoryStream(data, 0, length, true, true);
        result.Content = new ByteArrayContent(ms.GetBuffer());
        result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
        {
            FileName = id + ".pdf"
        };
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

        file.Dispose();
    }
    File.Delete(_path);
}
Corey Whaley
  • 66
  • 3
  • 11
  • Corey Whaley. I am in a same situation. Any luck resolving this without saving the pdf to the disk? – Beginer Apr 02 '18 at 20:01
  • @Beginer At the time this was the best solution. This ended up being a very convenient answer for me. Are there restrictions to you saving the PDF to disk? – Corey Whaley Apr 03 '18 at 17:38
0

inn your controller save your byte array (the pdf file bytes ) to temp file and make your controller return the link of the temp file and open it in another tab

[HttpGet]
public HttpResponseMessage Get(string thing1, string thing2) //thing2 will be a string[] eventually, once I am able to get 2-3 pdfs working
{
    byte[] data = response.PDFBytes[0] == null ? new byte[0] : response.PDFBytes[0];
    int length = response.PDFBytes[0] == null ? 0 : response.PDFBytes[0].Length;

    var stream = new MemoryStream(data, 0, length, true, true);

    result.Content = new ByteArrayContent(stream.GetBuffer());

    result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
    {
        FileName = "CheckedOutItems.pdf"
    };
    string TempPath="~/YourFileTempPath.pdf";
    using (FileStream file = new FileStream(Server.MapPath(TempPath), FileMode.Create, FileAccess.Write)) {
    stream.WriteTo(file);


    return Json(TempPath,JsonBehavior.AllowGet);
}

and in your Js Code

$.ajax({
    type: 'get',
    url: '../api/Controller',
    contentType: 'application/json; charset=utf-8',
    data: { thing1: item, thing2: item2 },
    datatype: 'json',
    success: function (result) {
       window.location.href=result;
    },
    error: function () {
        toastr.error('Error creating print.');
    }
});
Hasan Elsherbiny
  • 598
  • 2
  • 14
  • 31