下载 ASP.NET Core 8 中的 Pdf/图像/任何文件,其中文件来自 Web api 的 HttpResponseMessage.Content

问题描述 投票:0回答:1

我在 ASP.NET Core 中下载文件时遇到问题,或者可能是我没有编写正确的代码。

我有一个 ASP.NET Core Web API,其中包含一些处理

GetAllFiles
Upload
Download
文件的方法。

我的 API 控制器中有一种方法可以下载文件(此处显示的代码):

[HttpGet("{id}")]
public async Task<IActionResult> DownloadFile(Guid id)
{
    var fileInDb = pdfRepository.GetByIdAsync(x => x.Pdf_Pk == id, false);

    if (fileInDb == null)
    {
        return NotFound();
    }

    // var fileName = _data.PdfDetail.Where(x => x.Pdf_Pk == id).Select(x => x.FileName).FirstOrDefault();
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "root\\Files", fileInDb.Result.FileName);
    var provider = new FileExtensionContentTypeProvider();

    if (!provider.TryGetContentType(filePath, out var contentType))
    {
        contentType = "application/octet-stream";
    }

    var bytes = await System.IO.File.ReadAllBytesAsync(filePath);
    return File(bytes, contentType, Path.GetFileName(filePath));            
}

我正在归还文件。

我从我的网络应用程序的控制器调用此方法。

Download
方法代码:

public async Task<IActionResult> Download(Guid Id)
{
   return RedirectToAction("Index" ,await PdfServices.DownloadAsync<ApiResponse>(Id));
}

这里

PdfServices.DownloadAsync
是服务方法,代码如下:

public Task<T> DownloadAsync<T>(Guid Id)
{
    return SendAsync<T>(new ApiRequest()
    {
        type = APIRequestHeader.APIRequest.ApiType.Get,
        Data = Id,
        Url = ApiUrl + "/api/PdfManager/"+Id
    });
}

现在我调用这个

SendAsync
方法,该方法用于向 API 方法发送请求并查找内容,并且我在这里执行序列化/反序列化

public async Task<T> SendAsync<T>(ApiRequest request)
{
    try
    {
        var client = httpClientFactory.CreateClient("PdfManager");
        HttpRequestMessage message = new();
        message.Headers.Add("Accept", "Applicaiton/Json");
        message.RequestUri = new Uri(request.Url);

        if (request.Data != null)
        {
            message.Content = new StringContent(JsonConvert.SerializeObject(request.Data), Encoding.UTF8, "Application/Json");
        }

        switch(request.type)
        {
            case APIRequest.ApiType.Post:
                message.Method = HttpMethod.Post;
                break;

            case APIRequest.ApiType.Put:
                message.Method = HttpMethod.Put;
                break;

            case APIRequest.ApiType.Delete:
                message.Method = HttpMethod.Delete;
                break;

            default:
                message.Method = HttpMethod.Get;
                break;
        }

        HttpResponseMessage hrm = null;
        hrm = await client.SendAsync(message);
        var apiContent = await hrm.Content.ReadAsStringAsync();

        if (true)   // don't know what to write in this, to download this file
        {
            var readByte = hrm.Content.ReadAsByteArrayAsync();                    

            using(MemoryStream ms =new MemoryStream(readByte.Result))
            {
                var writer = new BinaryWriter(ms, Encoding.UTF8, false);

                var res = new FileContentResult(readByte.Result, hrm.Content.Headers.ContentType.MediaType);
                //return (T)res;
                var test = JsonConvert.DeserializeObject<T>(res);
            }
        }
        
        var apiResponse = JsonConvert.DeserializeObject<T>(apiContent);

        return apiResponse;
    }
    catch (Exception ex)
    {
        var dto = new ApiResponse
        {
            ErrorMessage = new List<string> { Convert.ToString(ex.ToString())},
            IsSuccess = false
        };
        var res = JsonConvert.SerializeObject(dto);
        var ApiResponse = JsonConvert.DeserializeObject<T>(res);

        return ApiResponse;
    }
}

现在,该方法将用于所有操作,例如

GettingAllFiles
UploadingFiles
DeletingFiles
以及
DownloadFile

因为我们从 API 控制器返回文件,所以我如何下载该文件?

我无法将内容读取为字符串:

 hrm.Content.ReadAsStringAsync();

因为我们的内容不是字符串,它包含文件

如果我将其读作

ByteArray
,那么我无法反序列化该对象,因为它会要求类型。

如何从 API 控制器下载此文件到内容中?我该如何阅读,返回什么?

c# asp.net-core-webapi asp.net-core-8
1个回答
0
投票

评论:

//this always returns type ApiResponse
public async Task<ApiResponse> SendAsync(ApiRequest request)
{
    try
    {
        var client = httpClientFactory.CreateClient("PdfManager");
        HttpRequestMessage message = new();
        message.Headers.Add("Accept", "Applicaiton/Json"); //this is spelled wrong and apparently you accept all kinds of stuff, not just json
        message.RequestUri = new Uri(request.Url);

        if (request.Data != null)
            message.Content = new StringContent(JsonConvert.SerializeObject(request.Data), Encoding.UTF8, "Application/Json");

        message.Method = request.type switch
        {
            APIRequest.ApiType.Post => HttpMethod.Post,
            APIRequest.ApiType.Put => HttpMethod.Put,
            APIRequest.ApiType.Delete => HttpMethod.Delete,
            _ => HttpMethod.Get,
        };

        var hrm = await client.SendAsync(message);

        //if it's json, deserialize as before and fuck off
        if (hrm.Content.Headers.ContentType?.MediaType == MediaTypeNames.Application.Json)
        {
            var apiContent = await hrm.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<ApiResponse>(apiContent);
        }

        //otherwise, who knows what it is. just give back the
        //content stream for the callsite to decide
        return new ApiResponse()
        {
            StatusCode = hrm.StatusCode,
            IsSuccess = hrm.IsSuccessStatusCode,
            Result = await hrm.Content.ReadAsStreamAsync(),
            ErrorMessage = new(),
        };
    }
    catch (Exception ex)
    {
        //not sure what's happening here
        var dto = new ApiResponse
        {
            ErrorMessage = new List<string> { Convert.ToString(ex.ToString())},
            IsSuccess = false
        };
        var res = JsonConvert.SerializeObject(dto);
        var ApiResponse = JsonConvert.DeserializeObject<ApiResponse>(res);

        return ApiResponse;
    }
}

现在,当您调用它时,您已经知道您正在获取 PDF,因此您将

object
投射到流并对其执行某些操作:

public async Task<IActionResult> DownloadAsync(Guid Id)
{
    var response = await SendAsync(new ApiRequest()
    {
        type = APIRequestHeader.APIRequest.ApiType.Get,
        Data = Id,
        Url = ApiUrl + "/api/PdfManager/" + Id
    });

    if (!response.IsSuccess)
        return new ContentResult() { StatusCode = 500, Content = "fucked" };

    using var pdfStream = response.Result as Stream;
    return new FileStreamResult(pdfStream, "application/pdf") { FileDownloadName = "Here's the document you wanted.pdf" };
}

或者类似的东西?

© www.soinside.com 2019 - 2024. All rights reserved.