使用ASP将PDF返回到浏览器.净的核心



我在ASP中创建了Wep API。Net核心返回PDF。下面是我的代码:

public HttpResponseMessage Get(int id)
{
    var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);           
    var stream = new System.IO.FileStream(@"C:Usersshoba_eswarDocumentsREquest.pdf", System.IO.FileMode.Open);
    response.Content = new StreamContent(stream);
    response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
    response.Content.Headers.ContentDisposition.FileName = "NewTab";
    response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
    return response;
}

但是它只返回JSON响应:

{
   "version":{
      "major":1,
      "minor":1,
      "build":-1,
      "revision":-1,
      "majorRevision":-1,
      "minorRevision":-1
   },
   "content":{
      "headers":[
         {
            "key":"Content-Disposition",
            "value":[
               "attachment; filename=NewTab"
            ]
         },
         {
            "key":"Content-Type",
            "value":[
               "application/pdf"
            ]
         }
      ]
   },
   "statusCode":200,
   "reasonPhrase":"OK",
   "headers":[
   ],
   "requestMessage":null,
   "isSuccessStatusCode":true
}

我做错了什么吗?

asp.net Core HTTPRequestMessage返回奇怪的JSON消息。. NET Core不支持返回HttpResponseMessage(你安装了什么包来访问该类型?)。

因此,序列化器只是将HttpResponseMessage的所有公共属性写入输出,就像处理任何其他不受支持的响应类型一样。

要支持自定义响应,必须返回IActionResult实现类型。有很多这样的例子。在您的情况下,我会查看FileStreamResult:

public IActionResult Get(int id)
{
    var stream = new FileStream(@"pathtofile", FileMode.Open);
    return new FileStreamResult(stream, "application/pdf");     
}

或者简单地使用PhysicalFileResult,其中流为您处理:

public IActionResult Get(int id)
{
    return new PhysicalFileResult(@"pathtofile", "application/pdf");
}
当然,所有这些都可以使用辅助方法来简化,例如Controller.File():
public IActionResult Get(int id)
{
    var stream = new FileStream(@"pathtofile", FileMode.Open);
    return File(stream, "application/pdf", "FileDownloadName.ext");
}

这只是抽象了FileContentResultFileStreamResult的创建(对于这个重载,是后者)。

或者如果你正在转换一个旧的MVC或Web API应用程序,不想一次转换所有的代码,添加对WebApiCompatShim (NuGet)的引用,并将当前代码包装在ResponseMessageResult:

public IActionResult Get(int id)
{
    var response = new HttpResponseMessage(HttpStatusCode.OK);           
    var stream = ...
    response.Content...
    return new ResponseMessageResult(response);
}

如果您不想使用return File(fileName, contentType, fileDownloadName),那么FileStreamResult不支持从构造函数或通过属性设置内容处置头。

在这种情况下,你必须在返回文件结果之前自己将响应头添加到响应中:

var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName("foo.txt");
Response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();

我不能评论CodeCaster的答案,因为我的声誉不够高。当尝试

public IActionResult Get(int id)
{
    using (var stream = new FileStream(@"pathtofile", FileMode.Open))
    {
        return File(stream, "application/pdf", "FileDownloadName.ext");
    }       
} 

we got a

ObjectDisposedException:无法访问已处置的对象。对象名称:"无法访问已关闭的文件。"System.IO.FileStream.BeginRead (byte []数组,int offset, int numBytes, AsyncCallback回调,对象状态)

我们去掉了using

   [HttpGet]
   [Route("getImageFile")]
   public IActionResult GetWorkbook()
   {
        var stream = new FileStream(@"pathToFile", FileMode.Open);
        return File(stream, "image/png", "image.png");
   }

那起作用了。这就是ASP。. NET Core 2.1在IIS Express中运行

我没有足够的声誉来发表这篇评论,所以作为回答发表。@CodeCaster的前3个解和@BernhardMaertl的解是正确的。

然而,对于那些可能不经常使用文件的人(像我一样),请注意,如果运行这段代码的进程(例如API)只有对文件的读权限,你需要在创建FileStream时指定第三个参数,否则默认行为是打开文件进行读/写,你会得到一个异常,因为你没有写权限。

@CodeCaster的第三个解决方案是这样的:

public IActionResult Get(int id)
{
    var stream = new FileStream(@"pathtofile", FileMode.Open, FileAccess.Read);
    return File(stream, "application/pdf", "FileDownloadName.ext");
}

相关内容

  • 没有找到相关文章

最新更新