Mam projekt Web API, który działa na serwerze. Ma on zwracać pliki PDF z dwóch różnych źródeł: rzeczywistego przenośnego pliku dokumentu (PDF) oraz łańcucha base64 przechowywanego w bazie danych. Problem, który mam, polega na wysłaniu dokumentu do klienta aplikacji MVC. Reszta to szczegóły na temat wszystkiego, co się wydarzyło i które już wypróbowałem.Jak zwrócić plik PDF z aplikacji Web API
Napisałem kod, który z powodzeniem przetłumaczył te dwa formaty na kod C#, a następnie (z powrotem) na formularz PDF. Pomyślnie przesłałem tablicę bajtów, która miała reprezentować jeden z tych dokumentów, ale nie mogę jej wyświetlić w przeglądarce (w nowej zakładce samodzielnie). Zawsze pojawia się błąd "nie można wyświetlić".
Niedawno zrobiłem sposób, aby przejrzeć dokumenty po stronie serwera, aby upewnić się, że przynajmniej mogę to zrobić. Dostaje dokument do kodu i tworzy z nim obiekt FileStreamResult, który następnie zwraca jako (niejawny rzut) ActionResult. Dostałem to, aby powrócić do kontrolera MVC po stronie serwera i wrzuciłem go do prostego zwrotu (bez widoku), który wyświetla plik PDF w porządku w przeglądarce. Jednak próba przejścia od razu do funkcji Web API po prostu zwraca to, co wygląda na reprezentację JSON obiektu FileStreamResult.
Kiedy próbuję uzyskać to, aby powrócić poprawnie do mojej aplikacji MVC klienta, to mówi mi, że "_buffer" nie może być ustawiony bezpośrednio. Niektóre komunikaty o błędach wskazujące, że niektóre właściwości zwracane i wrzucane do obiektu są prywatne i nie można uzyskać do nich dostępu.
Powyższa reprezentacja tablic bajtowych pliku PDF, po przetłumaczeniu na ciąg base64, wydaje się nie mieć tej samej liczby znaków, co łańcuch "_buffer" zwrócony w JSON przez obiekt FileStreamResult. Brakuje około 26k A na końcu.
Wszelkie pomysły na temat tego, jak poprawnie pobrać ten plik PDF? Mogę podać kod, jeśli jest to konieczne, ale musi istnieć jakiś znany sposób, aby zwrócić plik PDF z aplikacji Web API po stronie serwera do aplikacji MVC po stronie klienta i wyświetlić ją jako stronę internetową w przeglądarce.
P.S. Wiem, że aplikacja "po stronie klienta" nie jest technicznie po stronie klienta. Będzie to również aplikacja serwera, ale nie powinno to mieć znaczenia w tym przypadku. W stosunku do serwera Web API moja aplikacja MVC jest "stroną klienta".
Kod Uzyskania PDF:
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 Function, który dostaje od GetPDF:
[AcceptVerbs("GET","POST")]
public System.Web.Mvc.ActionResult getPdf()
{
System.Web.Mvc.ActionResult retVal = GetPDF();
return retVal;
}
Do wyświetlania PDF po stronie serwera:
public ActionResult getChart()
{
return new PDFController().GetPDF();
}
kodu w aplikacja MVC uległa zmianie d dużo z biegiem czasu. Tak jak teraz, nie przechodzi do etapu, w którym próbuje wyświetlać w przeglądarce. Przed tym dostaje błąd.
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.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/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>();
}
JSON dostaję od uruchamiania metody bezpośrednio z kontrolera API Web jest:
{
"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":""
}
ja skrócić "_buffer" bo to absurdalnie długi. Obecnie pojawia się komunikat o błędzie poniżej na linii powrotnej get_pdf (args, klucze)
Wyjątek szczegóły: Newtonsoft.Json.JsonSerializationException: nie można utworzyć wystąpienie typu System.Web.Mvc.ActionResult. Typ to interfejs lub klasa abstrakcyjna i nie można utworzyć instancji. Ścieżka "FileStream".
Powrót kiedy użyłem, aby uzyskać pusty czytnik PDF (. Czytelnik nie był pusty plik), kiedyś ten kod:
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);
}
wykomentowane jest kod od innych prób. Kiedy używałem tego kodu, zwróciłem tablicę bajtów z serwera. Wyglądało to następująco:
JVBER...NjdENEUx
Pokaż przykładowy kod, konkretne komunikaty o błędach itd –
@ Mr.T mam dodałem wszystko, co mogłem teraz dodać w mojej edycji. – Doctor93
Dlaczego używasz 'JObject' w ogóle w' get_pdf'? – Jacob