asp.net调用WinRAR来压缩文件

来源:互联网 发布:丸户史明 知乎 编辑:程序博客网 时间:2024/05/03 04:23
系统架构:.net web app
问题:客户反映无法从系统中下载文件
分析:排查发现该客户要下载的excel文件,约8M大小,应用系统服务器在北京,客户在广州,没有专线,无法下载看来似乎是必然的事了
解决办法:看来要解决问题,就得压缩文件了。

那就开整吧:首先,有一个问题,之前下载文件都是直接把datagrid中的数据以文件流的形式response到客户端,同时包括边框、背景色等都一并导入了excel中,使得文件更大了。所以要解决问题,第一步就是只把有用的数据信息保存到服务器上的临时excel文件中。关于怎么把数据写到excel中,我以前是这么做的insert into [Sheet1$](人员ID,,姓名)  values('" + dr("人员ID").ToString + "','" + dr("姓名").ToString + "'),参见
http://blog.csdn.net/eigo/archive/2006/03/23/635335.aspx,
但是,这样的办法没有灵活性,每当excel模板文件中的各列发生变化,就需要在修改程序。所以,现在改进一点,在写excel文件时,灵活一点,不再像上面那样写死要插入哪些列,而是从datatable中获取,代码如下:
Private Sub GenerateExcel( ByVal _time As String)
        Try
            Dim sql As String
            sql = " select distinct * from v_mView"
            sql = sql & "   where time='" + _time + "'
            Dim adp As New OleDb.OleDbDataAdapter(sql, New          OleDb.OleDbConnection(Application("ConnStr").ToString))
            Dim dt As New System.Data.DataTable
            adp.Fill(dt)
            adp.Dispose()

            Dim newfilename As String = Now.Ticks.ToString
            ViewState.Item("FileName") = ViewState("folder").ToString + "/" + newfilename + ".xls"
            Dim strConn As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + ViewState.Item("FileName").ToString + ";Extended Properties=Excel 8.0;"
            FileCopy(ViewState("folder").ToString + "/excel模板.xls", ViewState.Item("FileName").ToString)

            '写入excel
            Dim dr As DataRow
            Dim comm As New OleDbCommand("", New OleDb.OleDbConnection(strConn))
            comm.Connection.Open()
            For Each dr In dt.Rows
                comm.CommandText = "insert into [Sheet1$]("
                Dim columnsCount As Int32 = dt.Columns.Count
                Dim mStringbuilder As StringBuilder
                mStringbuilder = New StringBuilder(columnsCount * 200)
                Dim nRep As Int32
                For nRep = 0 To columnsCount - 1  '生成要插入的excel表列
                    mStringbuilder.Append(dt.Columns(nRep).ColumnName)
                    mStringbuilder.Append(",")
                Next
                mStringbuilder.Remove(mStringbuilder.Length - 1, 1)
                comm.CommandText = comm.CommandText + mStringbuilder.ToString
                comm.CommandText = comm.CommandText + ")"

                comm.CommandText = comm.CommandText + " values("   '生成values值
                mStringbuilder.Remove(0, mStringbuilder.Length) '先清空mStringbuilder
                For nRep = 0 To columnsCount - 1
                    mStringbuilder.Append("""")
                    mStringbuilder.Append(dr.Item(nRep).ToString)
                    mStringbuilder.Append("""")
                    mStringbuilder.Append(",")
                Next
                mStringbuilder.Remove(mStringbuilder.Length - 1, 1)
                comm.CommandText = comm.CommandText + mStringbuilder.ToString
                comm.CommandText = comm.CommandText + ")"
                Dim strtemp As String = comm.CommandText

                comm.ExecuteNonQuery()
            Next
            comm.Connection.Close()

            CompressExcel(ViewState.Item("FileName").ToString) '用WinRAR压缩后再下载
        Catch ex As Exception
             'do nothing
        End Try
    End Sub
现在,完成了第一步工作,接下来,需要进行实质性的调用WinRAR来压缩这个excel文件了,当然,前提是web server上应该安装了WinRAR,接下来看压缩文件的代码:
Private Sub CompressExcel(ByVal _filename As String)
        '先删除以前的rar文件,我们每次下载的rar文件都是以temp开头的
        Dim strFullFileName As String
        Dim dir As New System.IO.DirectoryInfo(ViewState("folder").ToString + "/")
        Dim fs As System.IO.FileInfo()
        Dim i As Int16
        fs = dir.GetFiles()

        For i = 0 To fs.GetLength(0) - 1
            If fs(i).Name.Substring(0, 4) = "temp" And fs(i).Name.Substring(fs(i).Name.Length - 4, 4) = ".rar" Then
                System.IO.File.Delete(fs(i).FullName)
            End If
        Next

        Dim the_rar As String
        Dim the_Reg As RegistryKey
        Dim the_Obj As Object
        Dim the_Info As String
        Dim the_StartInfo As ProcessStartInfo
        Dim the_Process As Process
        Dim newFilename As String

        Try
            the_Reg = Registry.ClassesRoot.OpenSubKey("Applications/WinRAR.exe/Shell/Open/Command")
            the_Obj = the_Reg.GetValue("")
            the_rar = the_Obj.ToString()
            the_Reg.Close()
            the_rar = the_rar.Substring(1, the_rar.Length - 7)
            newFilename = "temp" + Now.Ticks.ToString
            the_Info = " a " + "-ep " + newFilename + ".rar" + " " + _filename  'a为命令:压缩;-ep为开关:不把目录压缩进去;
            the_StartInfo = New ProcessStartInfo
            the_StartInfo.FileName = the_rar
            the_StartInfo.Arguments = the_Info
            the_StartInfo.WindowStyle = ProcessWindowStyle.Hidden
            the_StartInfo.WorkingDirectory = ViewState("folder").ToString
            the_Process = New Process
            the_Process.StartInfo = the_StartInfo
            the_Process.Start()
            Dim Sleeptime As Integer = 5000 '等待5秒钟,后台压缩
            System.Threading.Thread.Sleep(Sleeptime)
            mBS.DownLoad(Response, ViewState("folder").ToString + "/" + newFilename + ".rar")  'mBS已封装了下载文件方法
        Catch ex As Exception
            'do nothing
        Finally
            System.IO.File.Delete(_filename) ‘删除服务器上的那个临时的excel文件
        End Try
    End Sub
完了!
另外,附上从http://www.itpub.net/871060.html转的写excel的代码:
1、由dataset生成

public void CreateExcel(DataSet ds,string typeid,string FileName)
{
HttpResponse resp;
resp = Page.Response;
resp.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
resp.AppendHeader("Content-Disposition", "attachment;filename=" + FileName);
string colHeaders= "", ls_item="";
int i=0;

//定义表对象与行对像,同时用DataSet对其值进行初始化
DataTable dt=ds.Tables[0];
DataRow[] myRow=dt.Select("");
// typeid=="1"时导出为EXCEL格式文件;typeid=="2"时导出为XML格式文件
if(typeid=="1")
{
//取得数据表各列标题,各标题之间以/t分割,最后一个列标题后加回车符
for(i=0;i colHeaders+=dt.Columns[i].Caption.ToString()+"/t";
colHeaders +=dt.Columns[i].Caption.ToString() +"/n";
//向HTTP输出流中写入取得的数据信息
resp.Write(colHeaders);
//逐行处理数据
foreach(DataRow row in myRow)
{
//在当前行中,逐列获得数据,数据之间以/t分割,结束时加回车符/n
for(i=0;i ls_item +=row[i].ToString() + "/t";
ls_item += row[i].ToString() +"/n";
//当前行数据写入HTTP输出流,并且置空ls_item以便下行数据
resp.Write(ls_item);
ls_item="";
}
}
else
{
if(typeid=="2")
{
//从DataSet中直接导出XML数据并且写到HTTP输出流中
resp.Write(ds.GetXml());
}
}
//写缓冲区中的数据到HTTP头文件中
resp.End();


}

2.由datagrid生成:

public void ToExcel(System.Web.UI.Control ctl)
{
HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=Excel.xls");
HttpContext.Current.Response.Charset ="UTF-8";
HttpContext.Current.Response.ContentEncoding =System.Text.Encoding.Default;
HttpContext.Current.Response.ContentType ="application/ms-excel";//image/JPEG;text/HTML;image/GIF;vnd.ms-excel/msword
ctl.Page.EnableViewState =false;
System.IO.StringWriter tw = new System.IO.StringWriter() ;
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter (tw);
ctl.RenderControl(hw);
HttpContext.Current.Response.Write(tw.ToString());
HttpContext.Current.Response.End();
}
原创粉丝点击