Я використовую веб-API ASP.NET .
Я хочу завантажити PDF з C # з API (який API генерує).
Чи можу я просто повернути API byte[]
? а для програми C # я можу просто зробити:
byte[] pdf = client.DownloadData("urlToAPI");?
і
File.WriteAllBytes()?
Я використовую веб-API ASP.NET .
Я хочу завантажити PDF з C # з API (який API генерує).
Чи можу я просто повернути API byte[]
? а для програми C # я можу просто зробити:
byte[] pdf = client.DownloadData("urlToAPI");?
і
File.WriteAllBytes()?
Відповіді:
Краще повернути HttpResponseMessage із StreamContent всередині нього.
Ось приклад:
public HttpResponseMessage GetFile(string id)
{
if (String.IsNullOrEmpty(id))
return Request.CreateResponse(HttpStatusCode.BadRequest);
string fileName;
string localFilePath;
int fileSize;
localFilePath = getFileFromID(id, out fileName, out fileSize);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
UPD з коментаря patridge : Якщо хтось інший прийде сюди і хоче надіслати відповідь із байтового масиву замість фактичного файлу, ви захочете використовувати новий ByteArrayContent (someData) замість StreamContent (див. Тут ).
Я зробив наступну дію:
[HttpGet]
[Route("api/DownloadPdfFile/{id}")]
public HttpResponseMessage DownloadPdfFile(long id)
{
HttpResponseMessage result = null;
try
{
SQL.File file = db.Files.Where(b => b.ID == id).SingleOrDefault();
if (file == null)
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
// sendo file to client
byte[] bytes = Convert.FromBase64String(file.pdfBase64);
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = file.name + ".pdf";
}
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
}
Приклад з IHttpActionResult
in ApiController
.
[HttpGet]
[Route("file/{id}/")]
public IHttpActionResult GetFileForCustomer(int id)
{
if (id == 0)
return BadRequest();
var file = GetFile(id);
IHttpActionResult response;
HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);
responseMsg.Content = new ByteArrayContent(file.SomeData);
responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;
responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response = ResponseMessage(responseMsg);
return response;
}
Якщо ви не хочете завантажувати PDF і використовувати браузери, вбудовані в засобі перегляду PDF, замість цього видаліть наступні два рядки:
responseMsg.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
responseMsg.Content.Headers.ContentDisposition.FileName = file.FileName;
var file = GetFile(id);
. file.SomeData
є байтовим масивом ( byte[]
) і file.FileName
є string
.
Лише примітка для .Net Core
: Ми можемо використовувати FileContentResult
і встановити contentType, application/octet-stream
якщо хочемо надіслати необроблені байти. Приклад:
[HttpGet("{id}")]
public IActionResult GetDocumentBytes(int id)
{
byte[] byteArray = GetDocumentByteArray(id);
return new FileContentResult(byteArray, "application/octet-stream");
}
FileContentResult
викликається, FileDownloadName
щоб вказати ім'я файлу
Мені цікаво, чи був простий спосіб завантажити файл більш ... "загальним" способом. Я це придумав.
Це просто, ActionResult
що дозволить завантажити файл із виклику контролера, який повертає файл IHttpActionResult
. Файл зберігається в byte[] Content
. Ви можете перетворити його на потік, якщо це потрібно.
Я використав це для повернення файлів, що зберігаються у варбінарному стовпці бази даних.
public class FileHttpActionResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string FileName { get; set; }
public string MediaType { get; set; }
public HttpStatusCode StatusCode { get; set; }
public byte[] Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response = new HttpResponseMessage(StatusCode);
response.StatusCode = StatusCode;
response.Content = new StreamContent(new MemoryStream(Content));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = FileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaType);
return Task.FromResult(response);
}
}