0

My application is trying to display PDF stored in the database when user click on the icon link.

When the link is clicked, it will fire an Ajax call to Web service which using the ID to retrieve the PDF data in byte[] array.

The html component:

    <a href="#" onclick="getSPOD(<%=TransportationDocument != null ? TransportationDocument.BusinessID.ToString() : String.Empty %>);return false;">
        <img alt="SPOD" src="images/icons/adobe_acrobat_icon.png">
    </a>

The Ajax call:

function getSPOD(id) {
    $.ajax({
        type: "GET",
        url: `Services/MyService.asmx/RetrieveSPODData?id='${id}'`,
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            console.log(data);
        },
        error: function (textStatus, errorThrown) {
            console.log(textStatus);
            console.log(errorThrown);
        }
    });
}

The web service method:

[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
[WebMethod]
public HttpResponse RetrieveSPODData(string id)
{
    string query = @"Select * from dcmnts 
                         where BUSNSS_ID = :BUSNSS_ID";
    DataTable dataTable = new DataTable();
    OracleCommand command = null;
    OracleDataAdapter adapter = null;

    string ConnString = ConfigurationManager.ConnectionStrings["DbConnEnc"].ToString();

    byte[] data = null;
    using (OracleConnection connection = new OracleConnection(BaseEncryptor.DecryptString(ConnString)))
    {
        try
        {
            if (connection.State != ConnectionState.Open)
                connection.Open();
            command = new OracleCommand(query, connection);
            command.Parameters.Add(new OracleParameter("BUSNSS_ID", id));
            adapter = new OracleDataAdapter(command);

            adapter.Fill(dataTable);
            foreach (DataRow row in dataTable.AsEnumerable())
            {
                data = row.Field<byte[]>("SUMMARY_SPOD");
            }
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.AddHeader("Content-Disposition", "inline;filename=file.pdf");
            HttpContext.Current.Response.ContentType = "application/pdf";
            HttpContext.Current.Response.BinaryWrite(data);
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();

            return HttpContext.Current.Response;
        }
        finally
        {
            if (adapter != null) { adapter.Dispose(); adapter = null; }
            if (command != null) { command.Dispose(); command = null; }
        }
    }
}

Syntax-wise, there is no problem. However, I don't know how to display the pdf from there. By using HttpContext.Current.Response methods, I am able to open the PDF in a new tab if I run the web service directly from visual studio. However, if I do it through the web interface I have implemented, nothing happend. So I though I may need to return the HttpContext.Current.Response, I tried to log it to see what is in the data, I received unreadable data.

How should I display the PDF from byte[] from web service? What do I need to do for my web service to serve up the resulting file?

Method 2: Return byte[] data to the ajax call and use the following:

var file = new Blob([data.d], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL);

By doing this, the PDF file could not be open properly as if it is damaged

AngryOtter
  • 149
  • 9
  • Ignoring all the web service stuff, what if you just read a PDF file from disk into a `byte[]` - how would you display it? How does your program display anything? Is it a web app, a Windows Forms app, or something else? – NetMage Aug 19 '21 at 18:33
  • @NetMage it is a web app using webforms. I know how to save the pdf file to local disk or open it from the web service directly, but I need to display it on the browser tab, that's the whole point of it. – AngryOtter Aug 19 '21 at 18:40
  • Then you need to return the `byte[]` as a pdf file to the browser: see [this answer](https://stackoverflow.com/a/4089226/2557128). – NetMage Aug 19 '21 at 18:44
  • @NetMage that answer is for Asp.MVC, not Asp.Net webform. – AngryOtter Aug 19 '21 at 18:45
  • Sorry, fixed it to the web form version. – NetMage Aug 19 '21 at 18:45
  • @NetMage No problem. However, I have seen this link and if you look at my code I have already done that. I just didn't know how to move on from there. With the HttpContext.Current.Response.BinaryWrite(data); , nothing happened when the link is clicked. – AngryOtter Aug 19 '21 at 18:48
  • Your Ajax get expects `application/json` your web service returns `application/pdf`, they don't mix. It seems like your real question is how to display a PDF retrieved by an Ajax web service call. – NetMage Aug 19 '21 at 18:52
  • I think that is a [bad idea](https://stackoverflow.com/a/9901537/2557128), but [this answer is one way](https://stackoverflow.com/a/44630572/2557128). – NetMage Aug 19 '21 at 18:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/236208/discussion-between-angryotter-and-netmage). – AngryOtter Aug 19 '21 at 18:54

1 Answers1

1

AJAX IS NOT NEEDED:

    <a href="Services/ProofOfDeliveryData.asmx/RetrieveSPODData?id=<%=TransportationDocument != null ? TransportationDocument.BusinessID.ToString() : String.Empty %>" Target="_blank">
        <img alt="SPOD" src="images/icons/adobe_acrobat_icon.png">
    </a>

Just make so the link will directly goes to the web service and it is working wonder.

AngryOtter
  • 149
  • 9
  • very good, but why do you need a web service - isn't that just a regular web page? – NetMage Aug 19 '21 at 20:25
  • @NetMage Honestly It was really just the first logic flow that came up my mind. Also, since each user will have its own pdf, I don't think serving up pdf as page is ideal. – AngryOtter Aug 19 '21 at 21:01