我有一个使用 HttpGet 调用的 API。 API 验证调用并直接返回报告文件(Excel 或 CSV)。如果验证失败,它会返回一个 Json
Result
对象,其中包含错误代码和消息。
这是API函数:
<HttpGet>
Public Function AdvReport(APIKey As String, SubID As String) As Object
Dim lRes As New Result
Try
' Check Key
If APIKey Is Nothing OrElse APIKey.Length = 0 Then Return lRes.Init(Result.ResultCode.NoAction, "API Key is missing")
lRes = APIKeyClass.APIHit(APIKey)
If lRes.NoSuccess Then Return lRes
' Get RepID
If String.IsNullOrEmpty(SubID) Then Return lRes.Init(Result.ResultCode.NoAction, "SubID is missing")
SubID = Encrypter.Decrypt(SubID)
If SubID.Length = 0 OrElse Not IsNumeric(SubID) Then Return lRes.Init(Result.ResultCode.NoAction, "Invalid SubID")
' Load Advanced Report Subscription
Dim lSub As New AdvRepSubClass
lRes = lSub.Load(CInt(SubID))
If lRes.NoSuccess Then Return lRes
If Not lSub.API Then Return lRes.Init(Result.ResultCode.NoAction, "Report not enabled for API access")
' Generate report
If lRes.IsSuccess Then lRes = lSub.GetReportBin(Nothing, False)
If lRes.IsSuccess Then LogClass.Log(Nothing, "API AdvReport", "Report Name: " + lSub.Title + "; Result: " + If(lRes.IsSuccess, "Success; Rows Affected: " + lRes.RowsAffected.ToString, lRes.Info) + "; API Key: " + APIKey, LogClass.LogTable.AdvRep, lSub.AdvRepID)
' Download it
Try
DownloadByteArray(CType(lRes.RetInfo, Byte()), GetReportFileName(lSub.Title, lSub.RepType), False)
Return Nothing
Catch ex As Exception
lRes.Init(Result.ResultCode.Err, ex.Message)
End Try
Return lRes
Catch ex As Exception
Return lRes.Init(Result.ResultCode.Err, ex.Message)
End Try
End Function
这是代码
DownloadByteArray()
Public Sub DownloadByteArray(aContent As Byte(), aFileName As String, aPreview As Boolean)
Try
HttpContext.Current.Response.Buffer = False
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("Content-Disposition", If(aPreview, "inline", "attachment") + "; filename=""" & aFileName & """")
If aPreview Then HttpContext.Current.Response.ContentType = Helper.GetContentType(aFileName) Else HttpContext.Current.Response.ContentType = "application/octet-stream"
HttpContext.Current.Response.AddHeader("Content-Length", aContent.Length.ToString())
HttpContext.Current.Response.BinaryWrite(aContent)
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.SuppressContent = True
HttpContext.Current.ApplicationInstance.CompleteRequest()
Catch ex As Exception
Dim lUserID As String = If(HttpContext.Current.Session IsNot Nothing AndAlso HttpContext.Current.Session("UserID") IsNot Nothing, HttpContext.Current.Session("UserID").ToString, Nothing)
LogClass.Log(Nothing, lUserID, "DownloadByteArray", String.Concat("Doc: ", aFileName, "; Ex: ", ex.ToString()))
End Try
End Sub
代码运行良好,并且使用 API 调用在浏览器上成功下载文件。问题是,在 API 调用后,全局应用程序错误处理程序也会被触发并出现以下错误:
System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent. at System.Web.HttpResponse.set_StatusCode(Int32 value) at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseStatusAndHeadersAsync>d__31.MoveNext()
我明白该错误的含义。我假设该函数在发送 Http 标头后尝试将返回值设置为 Nothing。如何解决此问题并在文件发送后以某种方式“停止”该功能?
我通过不调用通用下载函数并仅内联写入文件返回来解决了该问题。
' If file required, download it
Try
Dim lResult As New HttpResponseMessage(HttpStatusCode.OK)
lResult.Content = New ByteArrayContent(CType(lRes.RetInfo, Byte()))
lResult.Content.Headers.ContentDisposition = New ContentDispositionHeaderValue("attachment") With {
.FileName = GetReportFileName(lSub.Title, lSub.RepType)
}
lResult.Content.Headers.ContentType = New MediaTypeHeaderValue("application/octet-stream")
Return lResult
Catch ex As Exception
lRes.Init(Result.ResultCode.Err, ex.Message)
End Try