首页 > 编程 > .NET > 正文

技巧:Asp.net直接保存文件到客户端

2024-07-10 13:08:43
字体:
来源:转载
供稿:网友

在我们的系统的编写过程中,应该有很多的时候需要客户下载文件.我第一次的做法(应该也是大部分人的做法吧?)是:

1 httpresponse response = httpcontext.current.response;
2 string js = "<script language=javascript>window.open('{0}');</script>";
3 js = string.format(js, url);
4 response.write(js);
5

  但是有个问题了,就是会被广告拦截软件直接拦截掉,另我非常的头痛,于是寻找更好的解决方法.看了用response.binarywrite写文件流一文之后觉得确实可以如此,修改代码如下:

1/**//**//**//// <summary>
2 /**//// 下载文件
3 /**//// </summary>
4 /**//// <param name="filename">文件物理地址</param>
5
6protected void downloadfile(string filename)
7 ...{
8 string savefilename = "test.xls";
9 int intstart = filename.lastindexof("/")+1;
10 savefilename = filename.substring(intstart,filename.length-intstart);
11 filestream myfilestream;
12 long filesize;
13
14 myfilestream = new filestream(filename,filemode.open);
15 filesize = myfilestream.length;
16
17 byte[] buffer = new byte[(int)filesize];
18 myfilestream.read(buffer, 0, (int)filesize);
19 myfilestream.close();
20
21 response.addheader("content-disposition", "attachment;filename="+savefilename);
22 response.contentencoding = system.text.encoding.getencoding("gb2312");
23 response.contenttype = "application/vnd.ms-excel";
24
25 response.binarywrite(buffer);
26 response.flush();
27 response.close();
28 response.end();
29
30 }

   但是有个严重的问题,就是文件格式。这样只是将流输出,且无法正确识别格式。还好,能人层出不穷, 柚子nan 提出了能否不考虑文件的类型,直接把文件显示到浏览器(response) 的想法正好切中我的要害所在,于是急忙研究了柚子nan的想法,修改出最后代码:

1 /**//**//**//// <summary>
2 /**//// 下载文件
3 /**//// </summary>
4 /**//// <param name="filename">文件物理地址</param>
5 protected void downloadfile(string filename)
6 ...{
7 string savefilename = "test.xls";
8 int intstart = filename.lastindexof("/")+1;
9 savefilename = filename.substring(intstart,filename.length-intstart);
10
11 response.clear();
12 response.charset = "utf-8";
13 response.buffer= true;
14 this.enableviewstate = false;
15 response.contentencoding = system.text.encoding.utf8;
16
17 response.appendheader("content-disposition","attachment;filename=" + savefilename);
18 response.writefile(filename);
19 response.flush();
20 response.close();
21
22 response.end();
23 }

使用昨天asp.net直接保存文件到客户端 中的方法,经过我的反复测试,各式文档都运行完全正常。于是昨晚修改了现有代码,修改了下载方法,以解决一直困扰自己的窗口拦截问题。

  早上本来还沾沾自喜,这下再也不用老跟客户解释为什么窗口会没掉了。可惜啊,人算不如天算。

  早上客户就反映下载的文件全是乱码。立马在本机进行测试,没问题。再同事的机器上试验,同样没问题。

  那应该是客户端的问题才是。只好让客户netmeeting演示一下她的操作过程。下载-〉保存-〉打开。这么简单的流程,不会做错吧?

  正在郁闷之际,突然脑光一闪,终于发现不一样的地方,立马试验,果然如此!

  到底有什么区别呢?请看操作图:
客人操作图
我的操作图
各位应该看出不同之处了吧?还看不出来?
这件事情的罪魁祸首就是:

  解决方法:使用lovecherry 的如何从注册表读取文件的contenttype 一文的方法

  修正代码:

1 /**//// <summary>
2 /// 下载文件
3 /// </summary>
4 /// <param name="filename">文件物理地址</param>
5 protected void downloadfile(string filename)
6 {
7
8 string savefilename = "test.xls";
9 int intstart = filename.lastindexof("//")+1;
10 savefilename = filename.substring(intstart,filename.length-intstart);
11
12 system.io.fileinfo fi=new system.io.fileinfo(filename);
13 string fileextname=fi.extension;
14 string default_content_type = "application/unknown";
15 registrykey regkey,fileextkey;
16 string filecontenttype;
17 try
18 {
19 regkey=registry.classesroot;
20 fileextkey=regkey.opensubkey(fileextname);
21 filecontenttype=fileextkey.getvalue("content type",default_content_type).tostring();
22 }
23 catch
24 {
25 filecontenttype=default_content_type;
26 }
27
28
29 response.clear();
30 response.charset = "utf-8";
31 response.buffer= true;
32 this.enableviewstate = false;
33 response.contentencoding = system.text.encoding.utf8;
34
35 response.appendheader("content-disposition","attachment;filename=" + savefilename);
36 response.contenttype=filecontenttype;
37
38 response.writefile(filename);
39 response.flush();
40 response.close();
41
42 response.end();
43 }
44

  最后得出结论:要实现柚子nan提出的能否不考虑文件的类型,直接把文件显示到浏览器(response),有一种方法,让客户端都不要隐藏已知的扩展名,但是这种方法是无法适应大部分电脑使用者的(一般只有比较熟悉电脑的人才会这样做吧?)

bbs 看中的方法,还没有试用,不知道有没有作用.

  private sub page_load(byval sender as system.object, byval e as system.eventargs) _
    handles mybase.load
    '在此处放置初始化页的用户代码
    ' 定义是否是 sql server 数据库,这里为false
    dim blnissqlserver as system.boolean = false
    dim strsql as string
    dim objdataset as new dataset()
    dim objconn as object
    dim strcnn as string
    if blnissqlserver then
      strcnn = "user id=sa;initial catalog=northwind;data source=./netsdk;"
      objconn = new system.data.sqlclient.sqlconnection(strcnn)
      objconn.open()
      dim objadapter as new system.data.sqlclient.sqldataadapter()
      strsql = "select * from customers where country='usa'"
      objadapter.selectcommand = new system.data.sqlclient.sqlcommand(strsql, objconn)
      objadapter.fill(objdataset)
    else
      strcnn = "provider=microsoft.jet.oledb.4.0;data source=" + server.mappath("test.mdb")
      objconn = new system.data.oledb.oledbconnection(strcnn)
      objconn.open()
      dim objadapter as new system.data.oledb.oledbdataadapter()
      strsql = "select top 10 title from document"
      objadapter.selectcommand = new system.data.oledb.oledbcommand(strsql, objconn)
      objadapter.fill(objdataset)
    end if
    dim oview as new dataview(objdataset.tables(0))
    datagrid1.datasource = oview
    datagrid1.databind()
    objconn.close()
    objconn.dispose()
    objconn = nothing
    if request.querystring("bexcel") = "1" then
      response.contenttype = "application/vnd.ms-excel"
      ' 从content-type header中去除charset设置
      response.charset = ""
      ' 关闭 viewstate
      me.enableviewstate = false
      dim tw as new system.io.stringwriter()
      dim hw as new system.web.ui.htmltextwriter(tw)
      ' 获取control的html
      datagrid1.rendercontrol(hw)
      ' 把html写回浏览器
      response.write(tw.tostring())
      response.end()
    end if
  end sub

,欢迎访问网页设计爱好者web开发。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表