Ext如何实现文件下载?(从服务器的固定目录下载文件)

时间:2022-11-12 09:08:45
后台是Struts2,页面是一个GridPanel的文件列表;要求点击“下载”后,弹出文件保存窗口;

页面截图如下面形式:

 序号     文件名称            文件类型      文件记录数       生成文件日期       下载次数        操作  
 
  1     e_20100909.xls         EXCEL         222                                   4           下载  
  2     A_20100909.xls         EXCEL          22                                   5           下载             
  3    数据源_20100909.txt     TXT             1                                   33          下载 
 

    我的思路是点击下载后,通过异步请求,将文件名传到后台,调用struts2自带的下载文件功能,根据文件名打开文件流返回到浏览器。。。
    但是始终不成功,还是经验不足啊,希望高人指点,提供一个好的解决办法:

26 个解决方案

#1


我的配置文件:
        
        <!-- 文件下载,支持中文附件名 -->
        <action name="fileDownloadAction" class="com.tydic.emc.webapp.action.sharefile.FileDownloadAction" method="download">
            <!-- 初始文件名 -->
            <param name="fileName">fileName</param>
            <result name="success" type="stream">
                <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                <param name="inputName">inputStream</param>
                <!-- 使用经过转码的文件名作为下载文件名,downloadFileName属性
                对应action类中的方法 getDownloadFileName() -->
                <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
                <param name="bufferSize">4096</param>
            </result>
        </action>



后台Action:

package com.tydic.emc.webapp.action.sharefile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;

public class FileDownloadAction implements Action {
// 初始的通过param指定的文件名属性
private String fileName;
    //下载文件原始存放路径
    private final static String DOWNLOADFILEPATH="/shareDownload/";

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
     try {
fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        this.fileName = fileName;
    }

    //从下载文件原始存放路径读取得到文件输出流
    public InputStream getInputStream() throws IOException {
     //拿到web app的绝对根路径
String rootpath = ServletActionContext.getServletContext().getRealPath("/");
//要下载的文件路径及文件名
String fileUrl = rootpath+"shareDownload\\"+fileName;
System.out.println("===fileUrl===>"+fileUrl);    
        //return ServletActionContext.getServletContext().getResourceAsStream(fileUrl);
return new ByteArrayInputStream("Struts 2 下载示例".getBytes());
    }
/** 提供转换编码后的供下载用的文件名 */
public String getDownloadFileName() {

String downloadFileName = fileName;

try {
downloadFileName = new String(downloadFileName.getBytes("ISO8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downloadFileName;
}
/**
 * 下载文件
 * 
 * @return
 */
public String download() {
System.out.println("=====fileName====>"+fileName);
System.out.println("===DOWNLOADFILEPATH+fileName===>"+DOWNLOADFILEPATH+fileName);
return SUCCESS;
}

    public String execute() {
        return SUCCESS;
    }

}




Extjs页面用的是异步请求向后台传要下载的文件名参数:

//文件共享下载
function downLoadFile(){

//拿到文件名和文件类型;
var selectedRecords = tableGrid.getSelectionModel().getSelections();
var fileName = selectedRecords[0].get('fileName');
var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
var url = "/emc/shareDownload/"+fileName; 

//window.open(url);
       
        //异步请求,调用struts2的文件下载功能?
Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,
    //成功返回后调用函数    
    success: function(){
    alert("返回成功!");
    //调用update函数,更新下载次数
    update();
    }    
    });
   // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
}

#2


请教高人啦!

#3


引用楼主 taowei20061122 的回复:
后台是Struts2,页面是一个GridPanel的文件列表;要求点击“下载”后,弹出文件保存窗口;

页面截图如下面形式:

 序号     文件名称            文件类型      文件记录数       生成文件日期       下载次数        操作  
 
  1     e_20100909.xls         EXCEL         222    ……


下载不需要异步的,直接加个文件链接。然后通过文件路径在服务器下载即可。
//文件共享下载
    function downLoadFile(){
        
        //拿到文件名和文件类型;
        var selectedRecords = tableGrid.getSelectionModel().getSelections();
        var fileName = selectedRecords[0].get('fileName');
        var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
        var url = "/emc/shareDownload/"+fileName; 
        
        //window.open(url);//这种方式不行么
       
        //异步请求,调用struts2的文件下载功能?
        Ext.Ajax.request({
               method: 'POST',
               //向后台Action传表单参数
               url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,//再说你这里的url好像不对啊,/sharefile/fileDownloadAction.action?download.html&ajax=true
fileDownloadAction这个action下载已经配置了method是download,不带download
               //成功返回后调用函数                   
               success: function(){
                   alert("返回成功!");
                   //调用update函数,更新下载次数
                   update();
               }                   
           });
       // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
    }

#4


我之前就是在网页上拼接URL,然后调用window.open(url),我要下载的文件只有三种格式TXT,EXCEL和XML;这种方式有弊端,不能满足需求:
   如果文件名有中文,则服务器不识别;通过改变tomcat的默认编码为UTF-8虽然可以解决这个问题,但是如果是TXT文件就直接在浏览器中打开了,不能弹出文件保存对话框;
   我的想法就是通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!
  

#5


  我的想法就是:前提不改变tomcat的默认编码;通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!

#6


引用 5 楼 taowei20061122 的回复:
  我的想法就是:前提不改变tomcat的默认编码;通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!

下载的时候乱码我也遇到过了,这个还是可以搞定的。
分get和默认方式,如果是get传递参数有中文就会乱码
public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        try {
            fileName = new String(fileName.getBytes(),"GBK");
            HttpSerlvetRequest request = ServletActionContext.getRequest();
            if (request.getMethod().equalsIgnoreCase("get")) {//get传参
                fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        this.fileName = fileName;
    }
就是在下载的时候,如果文件名乱码了会有异常的对不对。你就用这种方式判断
首次好像不会乱码,你要分情况处理。
这个思路肯定是可以解决乱码的。

还有如果是服务器不能识别的文件名称
可以用js进行编码传递过去
fileName = encodeURI(encodeURI("js客户端中文参数"))
window.open("url?fileName=" + fileName);
服务器端解码
URLDecoder.decode(fileName, "utf-8")

#7


谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:

    <package name="sharefile" extends="default" namespace="/sharefile">
        <action name="shareFileAction!*" class="shareFileAction">
           <result name="listShareFiles">/WEB-INF/pages/sharefile/shareFileList.jsp</result>            
        </action>
        <!-- 文件下载,支持中文附件名 -->
        <action name="fileDownloadAction!*" class="com.tydic.emc.webapp.action.sharefile.FileDownloadAction">
            <!-- 初始文件名 -->
            <param name="fileName">\shareDownload\数据源_20100909.txt</param>
            <result name="success" type="stream">
                <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                <param name="inputName">inputStream</param>
                <!-- 使用经过转码的文件名作为下载文件名,downloadFileName属性
                对应action类中的方法 getDownloadFileName() -->
                <param name="contentDisposition">attachment;filename="${fileName}"</param>
                <param name="bufferSize">4096</param>
            </result>
        </action>
    </package>


后台Action:

package com.tydic.emc.webapp.action.sharefile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;
import com.sun.java_cup.internal.internal_error;

public class FileDownloadAction implements Action {
// 初始的通过param指定的文件名属性
private String fileName ;
    //下载文件原始存放路径
    private final static String DOWNLOADFILEPATH="/shareDownload/";

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
     try {
fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        this.fileName = fileName;
    }

    //从下载文件原始存放路径读取得到文件输出流
    public InputStream getInputStream() throws IOException {
 
     //拿到web app的绝对根路径
//String rootpath = ServletActionContext.getServletContext().getRealPath("/");
//要下载的文件路径及文件名 String realPath=rootpath+"shareDownload\\"+fileName;
     String realPath="/shareDownload/"+fileName;
System.out.println("getInputStream fileName=>"+fileName+" realPath=>"+realPath);
     InputStream in=ServletActionContext.getServletContext().getResourceAsStream(realPath);
     /*
     int b = 0;
     while((b=in.read())!=-1) {
     System.out.println((char)b);
     }
     */
     if(null==in){
    
     System.out.println("Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. Check the <param name=\"inputName\"> tag specified for this action.检查action中文件下载路径是否正确.");  
     }
     //返回指定文件对应的输入流
     return ServletActionContext.getServletContext().getResourceAsStream(realPath);
}
/** 提供转换编码后的供下载用的文件名 */
public String getDownloadFileName() {

String downloadFileName = fileName;

try {
downloadFileName = new String(downloadFileName.getBytes("ISO8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downloadFileName;
}
/**
 * 下载文件
 * 
 * @return
 */
public String download() {
System.out.println("===DOWNLOADFILEPATH+fileName===>"+DOWNLOADFILEPATH+fileName);
return SUCCESS;
}
    public String execute() {
    
        return SUCCESS;
    }

}


Ext页面:

<script type="text/javascript">
function downLoad(){
     var str = '<a href="#" onclick="javascript:downLoadFile();return false"> <font color="green">下载</font> </a>';
     return str;
}

//文件共享下载
function downLoadFile(){

//拿到文件名和文件类型;
var selectedRecords = tableGrid.getSelectionModel().getSelections();
var fileName = selectedRecords[0].get('fileName');
var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
var url = "/emc/shareDownload"; 

//window.open(url+"?fileName="+encodeURI(encodeURI(fileName)));

        //异步请求,调用struts2的文件下载功能?
Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,
    //成功返回后调用函数    
    success: function(){
    alert("返回成功!");
    //调用update函数,更新下载次数
    update();
    }    
    });
   // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
}

//更新下载次数
function update() {

var selectedRecords = tableGrid.getSelectionModel().getSelections();
var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        
    Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/shareFileAction!update.html?ajax=true"/>' + selectedId,
    //成功返回后调用函数    
    success: function(){
    parent.closePopupWin();
    //重新加载数据,刷新列表
    parent.rightContentFrm.contentWindow.location.reload();
    }    
    });
}

</script>

执行流程==>点击下载后执行Action的download()方法返回SUCCESS;
    后台打印的测试语句如下:
===DOWNLOADFILEPATH+fileName===>/shareDownload/数据源_20100909.txt
getInputStream fileName=>数据源_20100909.txt realPath=>/shareDownload/数据源_20100909.txt

    可是并没有弹出文件保存对话框,但是也没有报错;不知道是什么原因呢?是哪里配置错了,还是这种下载方式行不通呢?还请指教!!!!!
    先去睡觉了......好困啊!

#8


hoojo大哥,帮忙看看!!!

#9


引用 7 楼 taowei20061122 的回复:
谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:
XML code

    <package name="sharefile" extends="default" namespace="/sharefile">
        <action name="shareFileAction!*"……

你的想法是好的,但是ajax好像不能实现异步下载的功能。如果要无刷新下载可以将
下载的资源的url赋给一个隐藏的iframe,用iframe请求下载地址完成下载功能。

#10


引用 9 楼 ibm_hoojo 的回复:
引用 7 楼 taowei20061122 的回复:

谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:
XML code

<package name="sharefile" extends="default" namespace="/sharefile">
<action name……

谢谢您啦!如果不用异步,但是又不脱离原来的Ext页面,还有其他的下载方式吗?我在网上找了很久,也没有找到好的解决方案!

#11


    还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/数据源_2010819.txt",这时就不行了;
    还望高人指点啊!!!!!

#12


求达人指点......

#13


引用 11 楼 taowei20061122 的回复:
    还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/数据源_2010819.txt",这时就不行了;
还……


你这样是直接链接到你的资源,并没有用struts action;
你下载的Action干什么用的,你写了这么多还配置了xml。你又不用它?
用FileDownloadAction 下载传递参数即可
url="/emc/shareDownload/e_2010819.txt";
<a href="FileDownloadAction.action?fileName=e_2010819.txt">下载</a>

#14


该回复于2010-12-15 16:03:01被版主删除

#15


引用 13 楼 ibm_hoojo 的回复:
引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/……

那是我采用的第一种思路,没走通;
我现在就是想问题简单化,不用Action处理了,直接window.open()打开资源;文件名是英文可以,一旦是中文就不行了,会报错,即资源找不到,报错:HTTP Status 404 - /emc/shareDownload/%E6%95%B0%E6%8D%AE%E6%BA%90_2010817.txt

#16


引用 15 楼 taowei20061122 的回复:
引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比……


所以就用action啊,action里面转码就可以了。上面不是给你说了么?
look #6

#17


引用 16 楼 ibm_hoojo 的回复:
引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.o……

    那种方式我用过了啊!乱码问题是可以解决,但那不是困难所在;关键是得不到文件流,没有出现预期的文件保存对话框啊!!!我在 #7楼已经提出过这个问题;就是上面Action里面贴出来的那句

      //返回指定文件对应的输入流
        return ServletActionContext.getServletContext().getResourceAsStream(realPath);
我认为这句话执行完后,应该是会有个文件保存对话框的;但是什么都没有,后台也没报错。。。。。。

#18


引用 17 楼 taowei20061122 的回复:
引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/……

并不是这句话运行完了弹出,你先把struts2的基本下载搞好了,这里的下载和其他的下载是一样的
只要你在jsp页面能下载,在js中也可以下载的
就是多一步js将中文件名转码,然后在action再转码
可以用js进行编码传递过去
fileName = encodeURI(encodeURI("js客户端中文参数"))
window.open("url?fileName=" + fileName);
服务器端解码
URLDecoder.decode(fileName, "utf-8")

#19


给个URL即可。

#20


引用 19 楼 fendy5201 的回复:
给个URL即可。
中文名的话,Tomcat找不到资源

#21


引用 18 楼 ibm_hoojo 的回复:
引用 17 楼 taowei20061122 的回复:

引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/s……

看18# 转换下就可以

#22


引用 21 楼 ibm_hoojo 的回复:
引用 18 楼 ibm_hoojo 的回复:

引用 17 楼 taowei20061122 的回复:

引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上……

谢谢大侠的指点!呵呵...问题终于解决了!

window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));

可以去节贴了!!!!!!!!!

#23


代码贴出,希望能给遇到相似问题的朋友一点启发!

window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));


后台代码在上面贴出来:
服务器端解码:URLDecoder.decode(fileName, "utf-8")

再次感谢hoojo

#24


代码贴出,希望能给遇到相似问题的朋友一点启发!
页面代码上面也有,关键点:
window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));


后台代码在上面贴出来:
服务器端解码:URLDecoder.decode(fileName, "utf-8")

再次感谢hoojo

#25


ext下载 急用  我初学者  能否加个扣扣 给我讲下 450198392  谢谢 

#26


还是没有解决问题,希望能给个详细的指导。

#1


我的配置文件:
        
        <!-- 文件下载,支持中文附件名 -->
        <action name="fileDownloadAction" class="com.tydic.emc.webapp.action.sharefile.FileDownloadAction" method="download">
            <!-- 初始文件名 -->
            <param name="fileName">fileName</param>
            <result name="success" type="stream">
                <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                <param name="inputName">inputStream</param>
                <!-- 使用经过转码的文件名作为下载文件名,downloadFileName属性
                对应action类中的方法 getDownloadFileName() -->
                <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
                <param name="bufferSize">4096</param>
            </result>
        </action>



后台Action:

package com.tydic.emc.webapp.action.sharefile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;

public class FileDownloadAction implements Action {
// 初始的通过param指定的文件名属性
private String fileName;
    //下载文件原始存放路径
    private final static String DOWNLOADFILEPATH="/shareDownload/";

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
     try {
fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        this.fileName = fileName;
    }

    //从下载文件原始存放路径读取得到文件输出流
    public InputStream getInputStream() throws IOException {
     //拿到web app的绝对根路径
String rootpath = ServletActionContext.getServletContext().getRealPath("/");
//要下载的文件路径及文件名
String fileUrl = rootpath+"shareDownload\\"+fileName;
System.out.println("===fileUrl===>"+fileUrl);    
        //return ServletActionContext.getServletContext().getResourceAsStream(fileUrl);
return new ByteArrayInputStream("Struts 2 下载示例".getBytes());
    }
/** 提供转换编码后的供下载用的文件名 */
public String getDownloadFileName() {

String downloadFileName = fileName;

try {
downloadFileName = new String(downloadFileName.getBytes("ISO8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downloadFileName;
}
/**
 * 下载文件
 * 
 * @return
 */
public String download() {
System.out.println("=====fileName====>"+fileName);
System.out.println("===DOWNLOADFILEPATH+fileName===>"+DOWNLOADFILEPATH+fileName);
return SUCCESS;
}

    public String execute() {
        return SUCCESS;
    }

}




Extjs页面用的是异步请求向后台传要下载的文件名参数:

//文件共享下载
function downLoadFile(){

//拿到文件名和文件类型;
var selectedRecords = tableGrid.getSelectionModel().getSelections();
var fileName = selectedRecords[0].get('fileName');
var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
var url = "/emc/shareDownload/"+fileName; 

//window.open(url);
       
        //异步请求,调用struts2的文件下载功能?
Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,
    //成功返回后调用函数    
    success: function(){
    alert("返回成功!");
    //调用update函数,更新下载次数
    update();
    }    
    });
   // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
}

#2


请教高人啦!

#3


引用楼主 taowei20061122 的回复:
后台是Struts2,页面是一个GridPanel的文件列表;要求点击“下载”后,弹出文件保存窗口;

页面截图如下面形式:

 序号     文件名称            文件类型      文件记录数       生成文件日期       下载次数        操作  
 
  1     e_20100909.xls         EXCEL         222    ……


下载不需要异步的,直接加个文件链接。然后通过文件路径在服务器下载即可。
//文件共享下载
    function downLoadFile(){
        
        //拿到文件名和文件类型;
        var selectedRecords = tableGrid.getSelectionModel().getSelections();
        var fileName = selectedRecords[0].get('fileName');
        var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
        var url = "/emc/shareDownload/"+fileName; 
        
        //window.open(url);//这种方式不行么
       
        //异步请求,调用struts2的文件下载功能?
        Ext.Ajax.request({
               method: 'POST',
               //向后台Action传表单参数
               url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,//再说你这里的url好像不对啊,/sharefile/fileDownloadAction.action?download.html&ajax=true
fileDownloadAction这个action下载已经配置了method是download,不带download
               //成功返回后调用函数                   
               success: function(){
                   alert("返回成功!");
                   //调用update函数,更新下载次数
                   update();
               }                   
           });
       // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
    }

#4


我之前就是在网页上拼接URL,然后调用window.open(url),我要下载的文件只有三种格式TXT,EXCEL和XML;这种方式有弊端,不能满足需求:
   如果文件名有中文,则服务器不识别;通过改变tomcat的默认编码为UTF-8虽然可以解决这个问题,但是如果是TXT文件就直接在浏览器中打开了,不能弹出文件保存对话框;
   我的想法就是通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!
  

#5


  我的想法就是:前提不改变tomcat的默认编码;通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!

#6


引用 5 楼 taowei20061122 的回复:
  我的想法就是:前提不改变tomcat的默认编码;通过异步将下载文件名传到后台,然后调用struts2自带的下载文件功能下载服务器指定目录下的文件。高人指点啊!!!

下载的时候乱码我也遇到过了,这个还是可以搞定的。
分get和默认方式,如果是get传递参数有中文就会乱码
public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        try {
            fileName = new String(fileName.getBytes(),"GBK");
            HttpSerlvetRequest request = ServletActionContext.getRequest();
            if (request.getMethod().equalsIgnoreCase("get")) {//get传参
                fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        this.fileName = fileName;
    }
就是在下载的时候,如果文件名乱码了会有异常的对不对。你就用这种方式判断
首次好像不会乱码,你要分情况处理。
这个思路肯定是可以解决乱码的。

还有如果是服务器不能识别的文件名称
可以用js进行编码传递过去
fileName = encodeURI(encodeURI("js客户端中文参数"))
window.open("url?fileName=" + fileName);
服务器端解码
URLDecoder.decode(fileName, "utf-8")

#7


谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:

    <package name="sharefile" extends="default" namespace="/sharefile">
        <action name="shareFileAction!*" class="shareFileAction">
           <result name="listShareFiles">/WEB-INF/pages/sharefile/shareFileList.jsp</result>            
        </action>
        <!-- 文件下载,支持中文附件名 -->
        <action name="fileDownloadAction!*" class="com.tydic.emc.webapp.action.sharefile.FileDownloadAction">
            <!-- 初始文件名 -->
            <param name="fileName">\shareDownload\数据源_20100909.txt</param>
            <result name="success" type="stream">
                <param name="contentType">application/octet-stream;charset=ISO8859-1</param>
                <param name="inputName">inputStream</param>
                <!-- 使用经过转码的文件名作为下载文件名,downloadFileName属性
                对应action类中的方法 getDownloadFileName() -->
                <param name="contentDisposition">attachment;filename="${fileName}"</param>
                <param name="bufferSize">4096</param>
            </result>
        </action>
    </package>


后台Action:

package com.tydic.emc.webapp.action.sharefile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;
import com.sun.java_cup.internal.internal_error;

public class FileDownloadAction implements Action {
// 初始的通过param指定的文件名属性
private String fileName ;
    //下载文件原始存放路径
    private final static String DOWNLOADFILEPATH="/shareDownload/";

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
     try {
fileName = new String(fileName.getBytes("ISO8859-1"),"GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
        this.fileName = fileName;
    }

    //从下载文件原始存放路径读取得到文件输出流
    public InputStream getInputStream() throws IOException {
 
     //拿到web app的绝对根路径
//String rootpath = ServletActionContext.getServletContext().getRealPath("/");
//要下载的文件路径及文件名 String realPath=rootpath+"shareDownload\\"+fileName;
     String realPath="/shareDownload/"+fileName;
System.out.println("getInputStream fileName=>"+fileName+" realPath=>"+realPath);
     InputStream in=ServletActionContext.getServletContext().getResourceAsStream(realPath);
     /*
     int b = 0;
     while((b=in.read())!=-1) {
     System.out.println((char)b);
     }
     */
     if(null==in){
    
     System.out.println("Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. Check the <param name=\"inputName\"> tag specified for this action.检查action中文件下载路径是否正确.");  
     }
     //返回指定文件对应的输入流
     return ServletActionContext.getServletContext().getResourceAsStream(realPath);
}
/** 提供转换编码后的供下载用的文件名 */
public String getDownloadFileName() {

String downloadFileName = fileName;

try {
downloadFileName = new String(downloadFileName.getBytes("ISO8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downloadFileName;
}
/**
 * 下载文件
 * 
 * @return
 */
public String download() {
System.out.println("===DOWNLOADFILEPATH+fileName===>"+DOWNLOADFILEPATH+fileName);
return SUCCESS;
}
    public String execute() {
    
        return SUCCESS;
    }

}


Ext页面:

<script type="text/javascript">
function downLoad(){
     var str = '<a href="#" onclick="javascript:downLoadFile();return false"> <font color="green">下载</font> </a>';
     return str;
}

//文件共享下载
function downLoadFile(){

//拿到文件名和文件类型;
var selectedRecords = tableGrid.getSelectionModel().getSelections();
var fileName = selectedRecords[0].get('fileName');
var fileType = selectedRecords[0].get('fileType');
        var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        //var params = "&fileName="+encodeURI(encodeURI(fileName));
        var params = "&fileName="+fileName;
        alert("params="+params); 
               
var url = "/emc/shareDownload"; 

//window.open(url+"?fileName="+encodeURI(encodeURI(fileName)));

        //异步请求,调用struts2的文件下载功能?
Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/fileDownloadAction!download.html?ajax=true"/>' + params,
    //成功返回后调用函数    
    success: function(){
    alert("返回成功!");
    //调用update函数,更新下载次数
    update();
    }    
    });
   // url: '<c:url value="/sharefile/shareFileAction!downLoadFile.html?ajax=true"/>' + params,
}

//更新下载次数
function update() {

var selectedRecords = tableGrid.getSelectionModel().getSelections();
var selectedId = "";
        var selectedId = "&selectedId="+selectedRecords[0].get('id');
        
    Ext.Ajax.request({
    method: 'POST',
    //向后台Action传表单参数
    url: '<c:url value="/sharefile/shareFileAction!update.html?ajax=true"/>' + selectedId,
    //成功返回后调用函数    
    success: function(){
    parent.closePopupWin();
    //重新加载数据,刷新列表
    parent.rightContentFrm.contentWindow.location.reload();
    }    
    });
}

</script>

执行流程==>点击下载后执行Action的download()方法返回SUCCESS;
    后台打印的测试语句如下:
===DOWNLOADFILEPATH+fileName===>/shareDownload/数据源_20100909.txt
getInputStream fileName=>数据源_20100909.txt realPath=>/shareDownload/数据源_20100909.txt

    可是并没有弹出文件保存对话框,但是也没有报错;不知道是什么原因呢?是哪里配置错了,还是这种下载方式行不通呢?还请指教!!!!!
    先去睡觉了......好困啊!

#8


hoojo大哥,帮忙看看!!!

#9


引用 7 楼 taowei20061122 的回复:
谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:
XML code

    <package name="sharefile" extends="default" namespace="/sharefile">
        <action name="shareFileAction!*"……

你的想法是好的,但是ajax好像不能实现异步下载的功能。如果要无刷新下载可以将
下载的资源的url赋给一个隐藏的iframe,用iframe请求下载地址完成下载功能。

#10


引用 9 楼 ibm_hoojo 的回复:
引用 7 楼 taowei20061122 的回复:

谢谢您耐心的给予回复!这两天有事没上来,现在要继续解决这个问题,麻烦帮我看下!
现在情况是这样的:

struts.xml下载部分的配置如下:
XML code

<package name="sharefile" extends="default" namespace="/sharefile">
<action name……

谢谢您啦!如果不用异步,但是又不脱离原来的Ext页面,还有其他的下载方式吗?我在网上找了很久,也没有找到好的解决方案!

#11


    还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/数据源_2010819.txt",这时就不行了;
    还望高人指点啊!!!!!

#12


求达人指点......

#13


引用 11 楼 taowei20061122 的回复:
    还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/数据源_2010819.txt",这时就不行了;
还……


你这样是直接链接到你的资源,并没有用struts action;
你下载的Action干什么用的,你写了这么多还配置了xml。你又不用它?
用FileDownloadAction 下载传递参数即可
url="/emc/shareDownload/e_2010819.txt";
<a href="FileDownloadAction.action?fileName=e_2010819.txt">下载</a>

#14


该回复于2010-12-15 16:03:01被版主删除

#15


引用 13 楼 ibm_hoojo 的回复:
引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比如:url="/emc/shareDownload/……

那是我采用的第一种思路,没走通;
我现在就是想问题简单化,不用Action处理了,直接window.open()打开资源;文件名是英文可以,一旦是中文就不行了,会报错,即资源找不到,报错:HTTP Status 404 - /emc/shareDownload/%E6%95%B0%E6%8D%AE%E6%BA%90_2010817.txt

#16


引用 15 楼 taowei20061122 的回复:
引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.open(url);可以打开一个窗口;但是当这个文件名为中文,比……


所以就用action啊,action里面转码就可以了。上面不是给你说了么?
look #6

#17


引用 16 楼 ibm_hoojo 的回复:
引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/emc为web应用的根目录,然后掉用window.o……

    那种方式我用过了啊!乱码问题是可以解决,但那不是困难所在;关键是得不到文件流,没有出现预期的文件保存对话框啊!!!我在 #7楼已经提出过这个问题;就是上面Action里面贴出来的那句

      //返回指定文件对应的输入流
        return ServletActionContext.getServletContext().getResourceAsStream(realPath);
我认为这句话执行完后,应该是会有个文件保存对话框的;但是什么都没有,后台也没报错。。。。。。

#18


引用 17 楼 taowei20061122 的回复:
引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/shareDownload/e_2010819.txt",其中/……

并不是这句话运行完了弹出,你先把struts2的基本下载搞好了,这里的下载和其他的下载是一样的
只要你在jsp页面能下载,在js中也可以下载的
就是多一步js将中文件名转码,然后在action再转码
可以用js进行编码传递过去
fileName = encodeURI(encodeURI("js客户端中文参数"))
window.open("url?fileName=" + fileName);
服务器端解码
URLDecoder.decode(fileName, "utf-8")

#19


给个URL即可。

#20


引用 19 楼 fendy5201 的回复:
给个URL即可。
中文名的话,Tomcat找不到资源

#21


引用 18 楼 ibm_hoojo 的回复:
引用 17 楼 taowei20061122 的回复:

引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上将资源的URL地址拼接,比如:url="/emc/s……

看18# 转换下就可以

#22


引用 21 楼 ibm_hoojo 的回复:
引用 18 楼 ibm_hoojo 的回复:

引用 17 楼 taowei20061122 的回复:

引用 16 楼 ibm_hoojo 的回复:

引用 15 楼 taowei20061122 的回复:

引用 13 楼 ibm_hoojo 的回复:

引用 11 楼 taowei20061122 的回复:

还有一种做法就是不需要后台Action处理,直接在页面上……

谢谢大侠的指点!呵呵...问题终于解决了!

window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));

可以去节贴了!!!!!!!!!

#23


代码贴出,希望能给遇到相似问题的朋友一点启发!

window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));


后台代码在上面贴出来:
服务器端解码:URLDecoder.decode(fileName, "utf-8")

再次感谢hoojo

#24


代码贴出,希望能给遇到相似问题的朋友一点启发!
页面代码上面也有,关键点:
window.location = encodeURI(encodeURI('download.html?path=' + '' + '&fileName=' + fileName));


后台代码在上面贴出来:
服务器端解码:URLDecoder.decode(fileName, "utf-8")

再次感谢hoojo

#25


ext下载 急用  我初学者  能否加个扣扣 给我讲下 450198392  谢谢 

#26


还是没有解决问题,希望能给个详细的指导。