none
导出功能不能用 RRS feed

  • 问题

  • 问题描述:GridView的导出功能报错,提示如下:
    文件“D:\Temp\YMCode\WebUI\Excel\采购\王颖.xls”正由另一进程使用,因此该进程无法访问该文件。

    相关代码:
    StreamWriter sw = File.CreateText(filepath);

    请教:这个问题是如何发生的,如何解决?


    zy
    2009年9月27日 5:32

答案

  • 您好,首先您的代码无需调用DownFile(HttpResponse response, string filename, string fullpath)方法即可下载。

    其次,DownFile(HttpResponse response, string filename, string fullpath)方法中有错误,您把断点设置到DownFile的catch里就能看到错误,也因为这个错误导致fs.Close();代码没有执行,也就是说刚创建的文件将一直被占用。所以当您再点击按钮时会出现您贴出的被占用的错误。
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 13:41
    版主
  •    DownFile(httpresponse, filename, filepath);方法 应该是viod类型才对
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 14:51
  • 关于第二点:提示已说明了,算法有问题。您单步跟踪一下就能发现。
    我简单改了一下。
    if ((fpos + size) > flen)
                        {
                            size = Convert.ToInt32(flen - fpos);
                            if (size == 0) { break; }
                            readdata = new byte[size];
                            isend = true;
                        }
    粗体字是增加的部分,知道原因后,您可以优化算法。
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 15:11
    版主

全部回复

  • 问题补充:上面的问题,在第一次导出时是没有问题的。但从第二次开始就不行了。
    zy
    2009年9月27日 5:45
  • 你好!

    这个问题是由于这个 XLS 同时被多个地方使用。解决方法如下:

    1. 检查你的程序有没有打开这个文件并且用完后有没有正常释放
    2. 采用文件名唯一方式,比如使用 Guid 做为文件名

    知识改变命运,奋斗成就人生!
    2009年9月27日 5:45
    版主
  • 请问X.X.Y:我如何能释放这个文件呢?望指教


    zy
    2009年9月27日 5:47
  • 操作完毕后
    调用sw.Close()方法;或者 dispose方法
    2009年9月27日 5:49
  • private void Export(Page page, DataTable tab, string filename)
            {
                HttpResponse httpresponse = page.Response;
                DataGrid datagrid = new DataGrid();
                datagrid.DataSource = tab.DefaultView;
                datagrid.AllowPaging = false;
                datagrid.HeaderStyle.BackColor = Color.White;
                datagrid.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
                datagrid.HeaderStyle.Font.Bold = false;
                datagrid.DataBind();
                httpresponse.AppendHeader("content-disposition", "attachment;filename=" + HttpUtility.UrlEncode(filename, Encoding.UTF8)); //filename="*.xls";
                httpresponse.ContentEncoding = Encoding.GetEncoding("gb2312");
                httpresponse.ContentType = "application/ms-excel";
                StringWriter tw = new StringWriter();
                HtmlTextWriter hw = new HtmlTextWriter(tw);
                datagrid.RenderControl(hw);

                #region 根据登录用户信息选择导出Excel文件路径和文件名
                string filepath = string.Empty;

                switch(Session["deptId"].ToString())
                {
                    case "1":
                    {
                        filepath = page.Server.MapPath("~/Excel/销售") + "\\" + filename;
                        break;
                    }
                    case "2":
                    {
                        filepath = page.Server.MapPath("~/Excel/采购") + "\\" + filename;
                        break;
                    }
                    case "3":
                    {
                        filepath = page.Server.MapPath("~/Excel/仓储") + "\\" + filename;
                        break;
                    }
                    case "4":
                    {
                        filepath = page.Server.MapPath("~/Excel/账务") + "\\" + filename;
                        break;
                    }
                    case "5":
                    {
                        filepath = page.Server.MapPath("~/Excel/生产计划") + "\\" + filename;
                        break;
                    }
                }
                #endregion

                StreamWriter sw = File.CreateText(filepath);
                sw.Write(tw.ToString());
                sw.Close();

                DownFile(httpresponse, filename, filepath);

                httpresponse.End();
            }

            private bool DownFile(HttpResponse response, string filename, string fullpath)
            {
                try
                {
                    response.ContentType = "application/octet-stream";

                    response.AppendHeader("content-disposition", "attachment;filename=" +
                    HttpUtility.UrlEncode(filename, Encoding.UTF8) + ";charset=gb2312");
                    FileStream fs = File.OpenRead(fullpath);
                    long flen = fs.Length;
                    int size = 102400;//每100k同时下载数据
                    byte[] readdata = new byte[size];//指定缓冲区的大小

                    if(size > flen)
                    {
                        size = Convert.ToInt32(flen);
                    }

                    long fpos = 0;
                    bool isend = false;

                    while(!isend)
                    {
                        if((fpos + size) > flen)
                        {
                            size = Convert.ToInt32(flen - fpos);
                            readdata = new byte[size];
                            isend = true;
                        }

                        fs.Read(readdata, 0, size);//读入一个压缩块
                        response.BinaryWrite(readdata);
                        fpos += size;
                    }

                    fs.Close();
                    File.Delete(fullpath);

                    return true;
                }
                catch
                {
                    return false;
                }
            }
    这是DataTable导出Excel的完全方法。你提到的sw.Close()已调用


    zy
    2009年9月27日 5:51
  • 你好!

    建议你使用 using 语句,这样执行时超时 using 代码块会自动释放

    using(StreamWriter s =  File.CreateText(@"C:\1.xml"))
    {
    
    }


    知识改变命运,奋斗成就人生!
    2009年9月27日 5:55
    版主
  •   StreamWriter sw = File.CreateText(filepath);
                sw.Write(tw.ToString());
                sw.Close();
    sw.Dispose();试试
    2009年9月27日 6:00
  • 你好,StreamWrite在编写代码的时候需要注意释放资源。

    可以使用

            StreamWriter sw = File.CreateText(filepath);
            ......
            sw.Dispose();

    也可以使用

            using (StreamWriter sw = File.CreateText(filepath))
            {
                ...
            }
    jon.valett@gmail.com
    2009年9月27日 6:21
    版主
  • 谢谢各位的回复。可能是我没有表达清楚。现在的问题出在:第一次点击导出能弹出有三个命令的窗口(打开,保存,取消)。如果我点取消后再次点击导出,就会报前面的错误。


    zy
    2009年9月27日 9:13
  • 取消代码是什么?
    2009年9月27日 12:24
  • 取消没有代码。点击导出按钮就是系统自动弹出一个导出Excel的窗口。
    zy
    2009年9月27日 12:53
  • ·FileStream fs = File.OpenRead(fullpath);这段没有调用dispose方法
    试试看
    2009年9月27日 13:05
  • 您好,首先您的代码无需调用DownFile(HttpResponse response, string filename, string fullpath)方法即可下载。

    其次,DownFile(HttpResponse response, string filename, string fullpath)方法中有错误,您把断点设置到DownFile的catch里就能看到错误,也因为这个错误导致fs.Close();代码没有执行,也就是说刚创建的文件将一直被占用。所以当您再点击按钮时会出现您贴出的被占用的错误。
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 13:41
    版主
  • 谢谢Jiyuan的回复。对你回复的内容,第一点的说法是错误的,如果不调用DownFile方法,的确可以导出Excel,但导出的Excel里是没有任何内容的;第二点的确是直接到Catch里了,但错误说明不太明白。出错的状态如下:在执行第二次While循环时,在response.BinaryWrite(readdata);这句报错。内容:Message = "指定的参数已超出有效值的范围。\r\n参数名: offset"。望指教。
    zy
    2009年9月27日 14:13
  •    long fpos = 0;改成int..........试试
    2009年9月27日 14:38
  • 谢谢Jiyuan的回复。对你回复的内容,第一点的说法是错误的,如果不调用DownFile方法,的确可以导出Excel,但导出的Excel里是没有任何内容的;第二点的确是直接到Catch里了,但错误说明不太明白。出错的状态如下:在执行第二次While循环时,在response.BinaryWrite(readdata);这句报错。内容:Message = "指定的参数已超出有效值的范围。\r\n参数名: offset"。望指教。
    zy

    第一点:把StreamWriter sw = File.CreateText(filepath);
                sw.Write(tw.ToString());
                sw.Close();

                DownFile(httpresponse, filename, filepath);
    都注释掉,然后改为:
    Response.Write(tw);

    • 已标记为答案 张烨 2009年9月27日 15:19
    • 取消答案标记 张烨 2009年9月27日 15:22
    2009年9月27日 14:48
    版主
  •    DownFile(httpresponse, filename, filepath);方法 应该是viod类型才对
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 14:51
  • 关于第二点:提示已说明了,算法有问题。您单步跟踪一下就能发现。
    我简单改了一下。
    if ((fpos + size) > flen)
                        {
                            size = Convert.ToInt32(flen - fpos);
                            if (size == 0) { break; }
                            readdata = new byte[size];
                            isend = true;
                        }
    粗体字是增加的部分,知道原因后,您可以优化算法。
    • 已标记为答案 张烨 2009年9月27日 15:19
    2009年9月27日 15:11
    版主
  • 谢谢mldark和Jiyuan的帮助。现在OK了。这个导出EXCEL的代码要弄懂才行。
    zy
    2009年9月27日 15:21
  • 不客气

    2009年9月27日 15:26