将动态创建的CSV发送回客户端进行下载

时间:2011-03-11 19:29:50

标签: asp.net vb.net csv download

我正在将一堆FOXPRO / FOXWEB应用转换为ASP.NET。

底层数据库仍然是foxpro(暂时)。

我正在将表传递给一些VB.NET代码,我希望将其转换为CSV文件并发送回客户端进行下载。它的工作原理!排序...它有时会起作用,但在其他时候,它不是问我是否要下载CSV文件,而是将文件喷出到浏览器窗口。

在asp方面,我传递了响应对象,表和csv文件名。

<%
   Dim xls_fn As String = "test01.csv"

   'OLEDB call to fill up 'tbl' ... this works.

   sendTableAsCSVtoClient(response, tbl, xls_fn)
%>

在文件clsCommon.vb中,我有以下代码:

Option Explicit On 
'Option Strict On

Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.Page
Imports System.IO
Imports Microsoft.VisualBasic
Imports System.Diagnostics
Imports System.Data
Imports System.Data.OleDb


Public Class clsCommon
    Inherits Page

    Public Shared Function enq(ByVal str As String) As String
        Dim dq As String
        dq = """"
        Return dq & str & dq
    End Function

    ' some other functions and subs defined in here ... blah blah blah
    ' ...

    Public Shared Function sendTableAsCSVtoClient(ByVal resp As HttpResponse, ByVal sqlTable As DataTable, ByVal xls_fn As String) As Boolean
        Dim r As DataRow
        Dim c As DataColumn
        Dim sep As String = ","
        Dim FileExtension As String
        Dim lcFileNameONLY As String
        Dim i As Integer
        Dim dq As String = """"

        FileExtension = UCase(Path.GetExtension(xls_fn))
        lcFileNameONLY = UCase(Path.GetFileNameWithoutExtension(xls_fn))

        resp.Clear()
        resp.ClearContent()
        resp.ClearHeaders()
        resp.ContentType = "application/vnd.ms-excel"
        resp.AddHeader("Content-Disposition", "inline; filename=" & lcFileNameONLY & ".csv")
        For Each c In sqlTable.Columns
            resp.Write(UCase(c.ColumnName) & sep)
        Next
        resp.Write(vbCrLf)

        For Each r In sqlTable.Rows
            For i = 0 To sqlTable.Columns.Count - 1
                resp.Write(enq(r(i)) & sep)
            Next
            resp.Write(vbCrLf)
        Next

        resp.End()
        Return True

    End Function

End Class
  1. 造成这种情况的原因是什么?
  2. 我如何绕过它?
  3. 我猜测数据源是一个表并不重要。 请注意,该文件是即时创建的,并且从不存在于服务器的文件系统中。

    TX, TFF

3 个答案:

答案 0 :(得分:2)

使用Content-Disposition而不是使用Inline的{​​{1}}标头,而是始终提示下载。

更改以下行:

Attachment

resp.AddHeader("Content-Disposition", "inline; filename=" & lcFileNameONLY & ".csv")

有关示例,请参阅thisthis

内联类型意味着浏览器可以自由呈现内联(在浏览器中),如果在知道如何。

请参阅this问题,询问为什么resp.AddHeader("Content-Disposition", "attachment; filename=" & lcFileNameONLY & ".csv") 有时会提示下载(与您的问题完全相反......)。

答案 1 :(得分:1)

问题是您的Content-disposition标题。它应该是"attachment"而不是"inline"

您可能还想将内容类型设置为"text/csv"而不是"application/vnd.ms-excel"。通过这种方式,您可以更加准确,如果他们更喜欢使用其他内容来处理CSV,那么它应该会更好。但是对于内部应用程序,也许vnd.ms-excel可能会更好用吗?

答案 2 :(得分:1)

我同意Oded和chmullig你应该改变Content-Disposition,但是我也建议使用缓冲区并用flush来完成响应:

 resp.Clear()
 resp.Buffer = true

 'build csv

 resp.Flush()
 resp.Close()

我相信对.End()的调用会抛出一个ThreadAbortException来停止执行,这可能会导致问题,具体取决于您处理异常的方式。 See here for more info