У меня есть проект веб-API, который работает на сервере. Он должен возвращать PDF файлы из двух разных источников: фактического портативного документа (PDF) и строки base64, хранящейся в базе данных. У меня возникла проблема с отправкой документа обратно в клиентское приложение MVC. В остальном это подробности обо всем, что произошло и что я уже пробовал.
Я написал код, который успешно переводит эти два формата в код С#, а затем (обратно) в PDF-форму. Я успешно передал массив байтов, который должен был представлять один из этих документов, но я не могу заставить его отображаться в браузере (на новой вкладке сам по себе). Я всегда получаю какую-то ошибку "невозможно отобразить".
Недавно я сделал способ просмотреть документы на стороне сервера, чтобы убедиться, что смогу, по крайней мере, сделать это. Он получает документ в код и создает FileStreamResult с ним, который затем возвращается как (неявный) ActionResult. Я получил это, чтобы вернуться к серверному контроллеру MVC и бросил его в простой возврат (без представления), который отображает PDF как раз в браузере. Однако попытка просто перейти к функции Web API просто возвращает то, что выглядит как JSON-представление FileStreamResult.
Когда я пытаюсь заставить это правильно вернуться к моему клиентскому MVC-приложению, он сообщает мне, что "_buffer" не может быть напрямую установлен. Некоторое сообщение об ошибке о том, что некоторые свойства, возвращаемые и переданные в объект, являются закрытыми и недоступны.
Вышеупомянутое представление байтового массива PDF, если оно переведено в строку base64, похоже, не имеет такого же количества символов, что и строка "_buffer", возвращаемая в JSON с помощью FileStreamResult. Он пропустил около 26k 'A в конце.
Любые идеи о том, как правильно вернуть этот PDF файл? Я могу предоставить код, если это необходимо, но должен быть какой-то известный способ возврата PDF файла из приложения веб-API на стороне сервера в клиентское приложение MVC и отображения его как веб-страницы в браузере.
PS Я действительно знаю, что приложение "клиентская сторона" не является технически на стороне клиента. Это также будет серверное приложение, но в этом случае это не имеет значения. По отношению к серверу веб-API мое приложение MVC является "клиентским".
Код Для получения 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, получаемая из GetPDF:
[AcceptVerbs("GET","POST")]
public System.Web.Mvc.ActionResult getPdf()
{
System.Web.Mvc.ActionResult retVal = GetPDF();
return retVal;
}
Для отображения на стороне сервера PDF:
public ActionResult getChart()
{
return new PDFController().GetPDF();
}
Код в приложении MVC сильно изменился с течением времени. То, как это происходит прямо сейчас, не доходит до того места, где он пытается отобразиться в браузере. Перед этим возникает ошибка.
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, который я получаю от запуска метода непосредственно от контроллера веб-API:
{
"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":""
}
Я сократил "буффер", потому что это смехотворно долго. В настоящее время я получаю сообщение об ошибке в строке возврата get_pdf (args, keys)
Сведения об исключении: Newtonsoft.Json.JsonSerializationException: Не удалось создать экземпляр типа System.Web.Mvc.ActionResult. Тип - это интерфейс или абстрактный класс и не может быть создан. Путь 'FileStream'.
Назад, когда я использовал пустой PDF-ридер (читатель был пустым, без файла), я использовал этот код:
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);
}
Прокомментирован код из некоторых других попыток. Когда я использовал этот код, я возвращал байтовый массив с сервера. Это выглядело как:
JVBER...NjdENEUx