Почему мой файл не возвращается с помощью запроса GET из моей функции Web API?

У меня есть функция, доступная через мой REST API, настроенный с помощью ASP.NET Web API 2.1, который должен вернуть изображение вызывающему. Для целей тестирования я просто хочу, чтобы он возвращал образец изображения, который я сохранил на своей локальной машине прямо сейчас. Вот способ:

public IHttpActionResult GetImage()
        {
            FileStream fileStream = new FileStream("C:/img/hello.jpg", FileMode.Open);
            HttpContent content = new StreamContent(fileStream);
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
            content.Headers.ContentLength = fileStream.Length;
            return Ok(content);
         }

Когда этот метод вызван, я не получаю изображение обратно вообще. Вот ответ, который я получаю:

{ "заголовки": [{ "Ключ": "Content-Type", "Значение": [ "изображение/JPEG" ]}, { "Ключ": "Content-Length", "Значение": [ "30399" ]}]}

Почему я не получаю данные изображения обратно как часть запроса? Как это можно решить?

Ответ 1

Одна из возможностей заключается в написании пользовательского IHttpActionResult для обработки ваших изображений:

public class FileResult : IHttpActionResult
{
    private readonly string filePath;
    private readonly string contentType;

    public FileResult(string filePath, string contentType = null)
    {
        this.filePath = filePath;
        this.contentType = contentType;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            var response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StreamContent(File.OpenRead(filePath))
            };

            var contentType = this.contentType ?? MimeMapping.GetMimeMapping(Path.GetExtension(filePath));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);

            return response;
        }, cancellationToken);
    }
}

который вы можете использовать в действии контроллера веб-API:

public IHttpActionResult GetImage()
{
    return new FileResult(@"C:\\img\\hello.jpg", "image/jpeg");
}

Ответ 2

Добавляя к тому, что упоминает @Darin, вспомогательный помощник Ok<T>(T content), который вы используете, на самом деле возвращает OkNegotiatedContentResult<T>, который по мере того, как имя указывает на ведение согласования содержимого. Поскольку вы не хотите согласовывать содержимое в этом случае, вам нужно создать пользовательский результат действия.

Ниже приведен пример того, как вы можете это сделать: http://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/ActionResults/ActionResults/Results/OkFileDownloadResult.cs

Ответ 3

Вы можете загрузить файл по следующему коду:

    HttpResponse response = HttpContext.Current.Response; 
    response.Clear();
    response.Buffer = false;
    response.BufferOutput = false;
    response.Charset = "UTF-8";
    response.ContentEncoding = System.Text.Encoding.UTF8;           
    response.AppendHeader("Content-disposition", "attachment; filename=" + fileName);
    response.Write(excelXml);
    response.Flush();
    response.End();
    HttpContext.Current.Response.End();

Ответ 4

Вы можете использовать следующий код для загрузки файла из web api:

 HttpResponseMessage objResponse = Request.CreateResponse(HttpStatusCode.OK);               
 objResponse.Content = new StreamContent(new FileStream(HttpContext.Current.Server.MapPath("~/FolderName/" + FileName), FileMode.Open, FileAccess.Read));
 objResponse.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
 objResponse.Content.Headers.ContentDisposition.FileName = FileName;
 return objResponse;