So geben Sie eine PDF-Datei aus einer Web-API-Anwendung zurück

Ich habe ein Web-API-Projekt, das auf einem Server ausgeführt wird. Es soll PDFs aus zwei verschiedenen Quellen zurückgeben: einer tatsächlichen PDF-Datei (Portable Document File) und einer Base64-Zeichenfolge, die in einer Datenbank gespeichert ist. Das Problem besteht darin, das Dokument an eine Client-MVC-Anwendung zurückzusenden. Der Rest sind die Details zu allem, was passiert ist und was ich bereits ausprobiert habe.

Ich habe Code geschrieben, der diese beiden Formate erfolgreich in C # -Code und dann (zurück) in ein PDF-Format übersetzt. Ich habe erfolgreich ein Byte-Array übertragen, das eines dieser Dokumente darstellen sollte, kann es jedoch nicht im Browser anzeigen (auf einer neuen Registerkarte). Ich erhalte immer eine Art Fehler "Kann nicht angezeigt werden".

Vor kurzem habe ich versucht, die Dokumente auf der Serverseite anzuzeigen, um sicherzustellen, dass ich sie zumindest dazu bringen kann, dies zu tun. Es nimmt das Dokument in den Code auf und erstellt damit ein FileStreamResult, das es dann als (implizites Cast-) ActionResult zurückgibt. Ich habe das, um zu einem serverseitigen MVC-Controller zurückzukehren und warf es in eine einfache Rückkehr (keine Ansicht), die das PDF gut im Browser anzeigt. Wenn Sie jedoch versuchen, direkt zur Web-API-Funktion zu wechseln, wird einfach eine JSON-Darstellung eines FileStreamResult zurückgegeben.

Wenn ich versuche, dies zu veranlassen, um ordnungsgemäß zu meiner Client-MVC-Anwendung zurückzukehren, wird mir mitgeteilt, dass "_buffer" nicht direkt festgelegt werden kann. Einige Fehlermeldungen, die darauf hinweisen, dass einige der Eigenschaften, die zurückgegeben und in ein Objekt geworfen werden, privat sind und auf die nicht zugegriffen werden kann.

Die oben genannte Byte-Array-Darstellung der PDF-Datei scheint bei der Übersetzung in eine Base64-Zeichenfolge nicht die gleiche Anzahl von Zeichen zu haben wie die Zeichenfolge "_buffer", die von einem FileStreamResult-Objekt in JSON zurückgegeben wird. Es fehlen ungefähr 26k 'A's am Ende.

Haben Sie eine Idee, wie Sie dieses PDF korrekt zurückgeben können? Ich kann bei Bedarf Code bereitstellen, aber es muss eine bekannte Möglichkeit geben, eine PDF-Datei von einer serverseitigen Web-API-Anwendung an eine clientseitige MVC-Anwendung zurückzugeben und sie als Webseite in einem Browser anzuzeigen.

P.S. Ich weiß, dass die "clientseitige" Anwendung technisch nicht clientseitig ist. Es wird auch eine Serveranwendung sein, aber das sollte in diesem Fall keine Rolle spielen. In Bezug auf den Web-API-Server ist meine MVC-Anwendung "clientseitig".

Cod Um pdf zu bekommen:

private System.Web.Mvc.ActionResult GetPDF()
{
    int bufferSize = 100;
    int startIndex = 0;
    long retval;
    byte[] buffer = new byte[bufferSize];
    MemoryStream stream = new MemoryStream();
    SqlCommand command;
    SqlConnection sqlca;
    SqlDataReader reader;

    using (sqlca = new SqlConnection(CONNECTION_STRING))
    {
        command = new SqlCommand((LINQ_TO_GET_FILE).ToString(), sqlca);
        sqlca.Open();
        reader = command.ExecuteReader(CommandBehavior.SequentialAccess);
        try
        {
            while (reader.Read())
            {
                do
                {
                    retval = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);
                    stream.Write(buffer, 0, bufferSize);
                    startIndex += bufferSize;
                } while (retval == bufferSize);
            }
        }
        finally
        {
            reader.Close();
            sqlca.Close();
        }
    }
    stream.Position = 0;
    System.Web.Mvc.FileStreamResult fsr = new System.Web.Mvc.FileStreamResult(stream, "application/pdf");
    return fsr;
}

API-Funktion, die von GetPDF abgerufen wird:

    [AcceptVerbs("GET","POST")]
    public System.Web.Mvc.ActionResult getPdf()
    {
        System.Web.Mvc.ActionResult retVal = GetPDF();
        return retVal;
    }

Zum Anzeigen der PDF-Serverseite:

public ActionResult getChart()
{
    return new PDFController().GetPDF();
}

Der Code in der MVC-Anwendung hat sich im Laufe der Zeit stark verändert. So wie es jetzt ist, erreicht es nicht das Stadium, in dem es versucht, es im Browser anzuzeigen. Es wird vorher ein Fehler gemeldet.

public async Task<ActionResult> get_pdf(args,keys)
{
    JObject jObj;
    StringBuilder argumentsSB = new StringBuilder();
    if (args.Length != 0)
    {
        argumentsSB.Append("?");
        argumentsSB.Append(keys[0]);
        argumentsSB.Append("=");
        argumentsSB.A,ppend(args[0]);
        for (int i = 1; i < args.Length; i += 1)
        {
            argumentsSB.Append("&");
            argumentsSB.Append(keys[i]);
            argumentsSB.Append("=");
            argumentsSB.Append(args[i]);
        }
    }
    else
    {
        argumentsSB.Append("");
    }
    var arguments = argumentsSB.ToString();
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        var response = await client.GetAsync(URL_OF_SERVER+"api/pdf/getPdf/" + arguments).ConfigureAwait(false);
        jObj = (JObject)JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
    }
    return jObj.ToObject<ActionResult>();
}

Der JSON-Code, den ich durch Ausführen der Methode direkt vom Web-API-Controller erhalte, lautet:

{
    "FileStream":{
        "_buffer":"JVBER...NjdENEUxAA...AA==",
        "_origin":0,
        "_position":0,
        "_length":45600,
        "_capacity":65536,
        "_expandable":true,
        "_writable":true,
        "_exposable":true,
        "_isOpen":true,
        "__identity":null},
    "ContentType":"application/pdf",
    "FileDownloadName":""
}

Ich habe "_buffer" gekürzt, weil es lächerlich lang ist. Ich erhalte derzeit die folgende Fehlermeldung in der Rückgabezeile von get_pdf (args, keys)

Ausnahmedetails: Newtonsoft.Json.JsonSerializationException: Es konnte keine Instanz vom Typ System.Web.Mvc.ActionResult erstellt werden. Type ist eine Schnittstelle oder abstrakte Klasse und kann nicht instanziiert werden. Pfad 'FileStream'.

Zurück, als ich einen leeren PDF-Reader bekommen habe (der Reader war leer. Keine Datei), habe ich diesen Code verwendet:

public async Task<ActionResult> get_pdf(args,keys)
{
    byte[] retArr;
    StringBuilder argumentsSB = new StringBuilder();
    if (args.Length != 0)
    {
        argumentsSB.Append("?");
        argumentsSB.Append(keys[0]);
        argumentsSB.Append("=");
        argumentsSB.Append(args[0]);
        for (int i = 1; i < args.Length; i += 1)
        {
            argumentsSB.Append("&");
            argumentsSB.Append(keys[i]);
            argumentsSB.Append("=");
            argumentsSB.Append(args[i]);
        }
    }
    else
    {
        argumentsSB.Append("");
    }
    var arguments = argumentsSB.ToString();
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/pdf"));
        var response = await client.GetAsync(URL_OF_SERVER+"api/webservice/" + method + "/" + arguments).ConfigureAwait(false);
        retArr = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
    }
    var x = retArr.Skip(1).Take(y.Length-2).ToArray();
    /*Response.Clear();
    Response.ClearContent();
    Response.ClearHeaders();
    Response.ContentType = "application/pdf";
    Response.AppendHeader("Content-Disposition", "inline;filename=document.pdf");
    Response.BufferOutput = true;
    Response.BinaryWrite(x);
    Response.Flush();
    Response.End();*/
    return new FileStreamResult(new MemoryStream(x),MediaTypeNames.Application.Pdf);
    }

Commented out ist Code aus anderen Versuchen. Als ich diesen Code verwendete, gab ich ein Byte-Array vom Server zurück. Es sah aus wie

JVBER...NjdENEUx

Antworten auf die Frage(2)

Ihre Antwort auf die Frage