使用 Asp.net Core 1.1 中的节点服务下载生成的 pdf 的 byte[]
Downloading byte[] of generated pdf using nodeservices in Asp.net Core 1.1
我正在尝试下载字节数组形式的 nodeServices 生成的 pdf 文件。这是我的原始代码:
[HttpGet]
[Route("[action]/{appId}")]
public async Task<IActionResult> Pdf(Guid appId, [FromServices] INodeServices nodeServices)
{
// generateHtml(appId) is a function where my model is converted to html.
// then nodeservices will generate the pdf for me as byte[].
var result = await nodeServices.InvokeAsync<byte[]>("./pdf",
await generateHtml(appId));
HttpContext.Response.ContentType = "application/pdf";
HttpContext.Response.Headers.Add("x-filename", "myFile.pdf");
HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "x-filename");
HttpContext.Response.Body.Write(result, 0, result.Length);
return new ContentResult();
}
此代码运行良好,它将在浏览器中显示 pdf 文件,例如。 chrome,当我尝试下载它时,我得到 "failed, network error"。
我在这里和那里搜索过,我看到了一些 return 文件的建议:
return File(result, "application/pdf");
那也没用,另一件事是添加 "Content-Disposition" header:
HttpContext.Response.Headers.Add("Content-Disposition", string.Format("inline;filename={0}", "myFile.pdf"));
别人建议用FileStreamResult
,也没用。
我意识到问题可能是关于我生成的文件 (byte[]) 没有路径或他自己的 link,所以我将字节保存到我的服务器,然后通过它的路径再次获取文件,然后到内存流,最后 return 一个包含内存流的文件:
var result = await nodeServices.InvokeAsync<byte[]>("./pdf", await generateHtml(appId));
var tempfilepath = Path.Combine(_environment.WebRootPath, $"temp/{appId}.pdf");
System.IO.File.WriteAllBytes(tempfilepath, result);
var memory = new MemoryStream();
using (var stream = new FileStream(tempfilepath, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/pdf", Path.GetFileName(tempfilepath));
有效!它在浏览器中显示文件,我可以下载它,但是,我不想在我的服务器上存储任何文件,我的问题是,我不能只下载文件而不需要存储它吗?
您仍然可以 return FileContentResult
而无需将字节数组转换为流。有一个 overload of the File()
method 将 fileContents
作为字节数组,将 contentType
作为字符串。
所以你可以重构为:
public async Task<IActionResult> Pdf(Guid appId, [FromServices] INodeServices nodeServices)
{
var result = await nodeServices.InvokeAsync<byte[]>("./pdf",
await generateHtml(appId));
return File(result, "application/pdf","myFile.pdf");
}
我正在尝试下载字节数组形式的 nodeServices 生成的 pdf 文件。这是我的原始代码:
[HttpGet]
[Route("[action]/{appId}")]
public async Task<IActionResult> Pdf(Guid appId, [FromServices] INodeServices nodeServices)
{
// generateHtml(appId) is a function where my model is converted to html.
// then nodeservices will generate the pdf for me as byte[].
var result = await nodeServices.InvokeAsync<byte[]>("./pdf",
await generateHtml(appId));
HttpContext.Response.ContentType = "application/pdf";
HttpContext.Response.Headers.Add("x-filename", "myFile.pdf");
HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "x-filename");
HttpContext.Response.Body.Write(result, 0, result.Length);
return new ContentResult();
}
此代码运行良好,它将在浏览器中显示 pdf 文件,例如。 chrome,当我尝试下载它时,我得到 "failed, network error"。
我在这里和那里搜索过,我看到了一些 return 文件的建议:
return File(result, "application/pdf");
那也没用,另一件事是添加 "Content-Disposition" header:
HttpContext.Response.Headers.Add("Content-Disposition", string.Format("inline;filename={0}", "myFile.pdf"));
别人建议用FileStreamResult
,也没用。
我意识到问题可能是关于我生成的文件 (byte[]) 没有路径或他自己的 link,所以我将字节保存到我的服务器,然后通过它的路径再次获取文件,然后到内存流,最后 return 一个包含内存流的文件:
var result = await nodeServices.InvokeAsync<byte[]>("./pdf", await generateHtml(appId));
var tempfilepath = Path.Combine(_environment.WebRootPath, $"temp/{appId}.pdf");
System.IO.File.WriteAllBytes(tempfilepath, result);
var memory = new MemoryStream();
using (var stream = new FileStream(tempfilepath, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/pdf", Path.GetFileName(tempfilepath));
有效!它在浏览器中显示文件,我可以下载它,但是,我不想在我的服务器上存储任何文件,我的问题是,我不能只下载文件而不需要存储它吗?
您仍然可以 return FileContentResult
而无需将字节数组转换为流。有一个 overload of the File()
method 将 fileContents
作为字节数组,将 contentType
作为字符串。
所以你可以重构为:
public async Task<IActionResult> Pdf(Guid appId, [FromServices] INodeServices nodeServices)
{
var result = await nodeServices.InvokeAsync<byte[]>("./pdf",
await generateHtml(appId));
return File(result, "application/pdf","myFile.pdf");
}