使用和反序列化 FileStreamResult Blazor

Mat*_*ynn 2 c# asp.net-core blazor asp.net-core-3.1 blazor-webassembly

我有一个控制器端点,它提供如下文件服务;

    [HttpGet]
    [ProducesResponseType(typeof(FileStreamResult), 200)]
    [Route("{documentId}")]
    public IActionResult GetDocumentImage(int documentId)
    {
        var response = _service.Get(documentId);

        HttpAssert.Success(response);
        HttpAssert.IsNotNull(response);

        Stream stream = new MemoryStream(response.Result.Data);

        if (stream == null)
            return NotFound();

        return File(stream, response.Result.MimeType); 
    }
Run Code Online (Sandbox Code Playgroud)

src当设置为标签时,这非常有效img,并且可以确认文件是否已成功发送。

我想在页面中使用结果blazor razor。我使用反序列化调用

var responseContent = await response.Content.ReadAsStringAsync();

if (response.IsSuccessStatusCode)
{
 var result = JsonConvert.DeserializeObject<T>(responseContent);
 return new ServiceResponse<T> { Result = result, HasError = false, HttpErrorCode = -1, Error = null };
}
Run Code Online (Sandbox Code Playgroud)

但是,当我反序列化为object(with JsonConvert.DeserializeObject<T>(responseContent))

ex.Message当我调试并尝试在我得到的监视窗口中进行评估时,会抛出错误,但没有

'解析值时遇到意外字符:%。路径“”,第 0 行,位置 0。”

在这种情况下返回的是 PDF 文件。谁能指导我哪里出错了?

Uma*_*air 5

正如 TomTom 提到的,您无法将 PDF 转换为 json,PDF 不像文本或 json 文件。

因此,在 Blazor 中,您必须按照以下方式进行操作。

当您从端点返回结果时,它将是一个流。因此,您可以执行以下操作来从端点获取流

var fileStream = new FileStream()
{
    Stream = await httpResponseMessage.Content.ReadAsStreamAsync(),
    Filename = $"someFile.pdf"
};
Run Code Online (Sandbox Code Playgroud)

获取文件流后,您必须将其转换为 byte

byte[] bytes;
using (var memoryStream = new System.IO.MemoryStream())
{
    fileStream.Stream.CopyTo(memoryStream);
    bytes = memoryStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

一旦您将其放入字节数组中,它现在就采用数组格式,我们现在可以通过用户浏览器使用和下载它。您必须创建以下 js 来触发 Blazor 中的浏览器下载

这里我们基本上是在 HTML DOM 中创建一个锚点并触发一个点击事件(源代码):

var saveAsFile = function (filename, bytesBase64) {
    var link = document.createElement('a');
    link.download = filename;
    link.href = "data:application/octet-stream;base64," + bytesBase64;
    document.body.appendChild(link); // Needed for Firefox
    link.click();
    document.body.removeChild(link);
}
Run Code Online (Sandbox Code Playgroud)

我们可以在 Blazor C# 代码中调用以下内容并通过JSInterop触发此操作

await JsRunTime.InvokeAsync<object>("saveAsFile", fileStream.Filename,
    Convert.ToBase64String(bytes));
Run Code Online (Sandbox Code Playgroud)