我在 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 控制器下载此文件到内容中?我该如何阅读,返回什么?
评论:
//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" };
}
或者类似的东西?