使用web api下载文件

时间:2014-11-07 23:02:47

标签: asp.net-web-api download

我试图在webapi控制器中编写动作以允许下载文件。 但由于一些奇怪的原因,代码不起作用。

这是我的代码:

<RoutePrefix("api/files")>
Public Class PermitFilesController
    Inherits ApiController

    <Route("download")>
    public function GetFile() As HttpResponseMessage 

        Dim fStream as FileStream =  File.Open("C:\Projects\1234.pdf", FileMode.Open, FileAccess.Read )
        Dim response = Request.CreateResponse(HttpStatusCode.OK)
        response.Content = new StreamContent(fStream)
        'response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        'response.Content.Headers.ContentDisposition.FileName = Path.GetFileName(fStream.Name)
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf")
        return response
    End Function

我尝试只使用浏览器中的网址下载:

localhost:<myport>/api/files/download

错误(在Chrome中)是错误代码:ERR_CONNECTION_RESET 在FF中,它甚至更奇怪:它将我重定向到www.localhost.com:/ ...具有相同的错误 - 主机连接重置

我在代码中放了一个断点,我注意到代码被调用了两次(一旦我从最后一行退出跟踪,它就会被再次调用到第一行)。

我在这个控制器中有其他几个动作,它们都可以正常工作。

任何人都知道我做错了什么?


修改

我创办了Fiddler,现在我的浏览器显示了这个错误:

  

[Fiddler] ReadResponse()失败:服务器未返回响应   对于这个请求。服务器返回0个字节。


修改

我想提一下,webapi已集成到传统的经典asp.net应用程序中

初始化代码如下:

在global.asax.Application_Start

WebApiHelper.Initialize
....
....
Public Class WebApiHelper

  Public Shared Sub Initialize()
    GlobalConfiguration.Configuration.MessageHandlers.Add(New BasicAuthMessageHandler() With { _
             .PrincipalProvider = New MPNAuthProvider() _
           })

    AreaRegistration.RegisterAllAreas()

    WebApiConfig.Register(GlobalConfiguration.Configuration)
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
    RouteConfig.RegisterRoutes(RouteTable.Routes)

    GlobalConfiguration.Configuration.EnsureInitialized()
End Sub

....

MPNAuthProvider用于确保对某些webapi控制器的身份验证访问

Public Class MPNAuthProvider
  Implements IProviderPrincipal

  Public Function CreatePrincipal(username As String, password As String) As IPrincipal Implements IProviderPrincipal.CreatePrincipal

    Dim userID As Integer = 0
    If Not UserData.ValidateUser(username, password, userID) Then Return Nothing

    Dim identity = New GenericIdentity(userID)
    Dim principal = New GenericPrincipal(identity, {"User"})
    Return principal
  End Function

End Class

还有什么我应该检查看看会发生什么?

谢谢

1 个答案:

答案 0 :(得分:3)

初始解决方案

根据Julien Jacobs的建议,我将我的代码测试成一个单独的独立webapi项目,事实证明代码是正确的。

所以我开始研究web.config。

我找到了以下必须注释掉的设置:

<system.web>
....
  <httpModules>
    <add name="RadUploadModule" type="Telerik.Web.UI.RadUploadHttpModule" />
    <add name="RadCompression" type="Telerik.Web.UI.RadCompression" />
  </httpModules>

<modules runAllManagedModulesForAllRequests="true">
  <remove name="RadUploadModule" />
  <remove name="RadCompression" />
  <add name="RadUploadModule" type="Telerik.Web.UI.RadUploadHttpModule" preCondition="integratedMode" />
  <add name="RadCompression" type="Telerik.Web.UI.RadCompression" preCondition="integratedMode" />
</modules>

在我评论它们之后,代码开始正常工作。

但事实证明这不是理想的解决方案,所以请继续阅读......


更新了解决方案

在对应用程序进行更多测试之后,我意识到RadCompression虽然不是绝对必需,但对于使用Telerik Ajax的Web应用程序非常有用,因为它为所有ajax流量提供透明的动态压缩(加上viewstate,已配置)

因为我禁用了它,应用程序开始变慢。

所以我必须找到一种重新启用RadCompression的方法,但是对某些请求(例如webapi端点下载文件)禁用它。

解决方案是:

为RadCompression配置添加特殊配置部分

<configSections>
 <sectionGroup name="telerik.web.ui">
    <section name="radCompression" type="Telerik.Web.UI.RadCompressionConfigurationSection, Telerik.Web.UI, PublicKeyToken=121fae78165ba3d4" allowDefinition="MachineToApplication" requirePermission="false"/>
  </sectionGroup>
  ....
</configSections>    

在system.web \ httpModules中添加处理程序

<system.web>
  ....
  <httpModules>
    <add name="RadCompression" type="Telerik.Web.UI.RadCompression" />
  </httpModules>

在system.webServer \ modules

中添加处理程序
<system.webServer>
  <modules runAllManagedModulesForAllRequests="false">
    <add name="RadCompression" type="Telerik.Web.UI.RadCompression" preCondition="managedHandler" />
  </modules>
</system.webServer>

关键部分,为特定请求(URI)禁用RadCompression,添加一个新的配置部分,如下所示

 <telerik.web.ui>
    <radCompression enablePostbackCompression="true">
      <excludeHandlers>
        <!--This will match every api/permitfiles/download file regardless of its location in the web site-->          <add handlerPath="api/permitfiles/download" matchExact="false"/>

      </excludeHandlers>
    </radCompression>
  </telerik.web.ui>

通过这些更改,RadCompression在应用程序中为所有请求全局授权,但仅限于特定请求(如webapi文件下载)