struts2文件下载之注解方式和文件不存在的处理方法

来源:互联网 发布:杜蕾斯网络代理 编辑:程序博客网 时间:2024/06/08 12:19

在用struts2做文件下载的时候,我们可能大部分用的都是在struts.xml里面做配置,其实,我们用注解的方式照样

可以做文件下载。

在Action中增加如下两个方法:

    private String fileName;//加上get和 set方法


    public String downloadFile(){
        return "download";
    }
    
    public InputStream getInputStream(){
        String dir = "/downloads/"+fileName;

        //取相对路径,此相对路径是取webRoot下面的相对路径
        return ServletActionContext.getServletContext().getResourceAsStream(dir);
    }

写完后,添加头部注解

@Results({ 
    @Result(name = "download", type="stream",params={
            "contentType","application/octet-stream",//这里是用octet-stream,这样可以表示任意文件类型
            "inputName","inputStream",
            "contentDisposition","attachment;filename=${fileName}",
            "bufferSize","4096"            
    }),   
})

仔细观察注解的写法,再对比struts.xml文件里面的写法,其实它们写法都差不多,步骤都是完全一样的。不过这里要注意一下:

①在"attachment;filename=${fileName}"这里,${fileName}表示从前台页面传过来的要下载的文件的名称,也即Action中的fileName值

②${fileName}前后不要加单/双引号,如果你写成"attachment;filename='${fileName}'",那么下载的文件名也会有两个''引号(但是在struts.xml配置文件里面写的话,可以加引号,并且最好加引号。此为不同点!)注意:此处还有个小Bug,后面再解释!


写完后,就可以写个jsp去测试了!

正常情况下,程序已经完成,如果前台页面传递过来的那个要下载的文件在服务器中并不存在的话,这个程序就会报错,给用户很不好的印象。所以,我们要对文件不存在这种情况作进一步的处理。


处理的方法有多种,可以在点击下载文件的链接后,先通过ajax访问Action,如果文件不存在,给出弹出框提示用户此文件不存在,如果文件存在,再通过其他途径(比如form表单的方式)访问Action,正常下载文件。还有就是,当出现错误界面后,跳转到错误页面,这也是一种解决办法。


而我采用的是另外的方法:在Action中再定义一个message变量,如果发现需要下载的文件不存在,则给message赋值,比如message=“您要下载的文件不存在”,并跳转回下载页面,在下载的jsp页面用js判断,如果返回的message有值(文件存在的情况下message没有值),则给出弹窗(其他提示方法也行)。优化后的代码如下:


private String fileName;
private String message;
    public String downloadFile(){
        String dir = "/downloads/"+fileName;
        if(null ==ServletActionContext.getServletContext().getResourceAsStream(dir)){
            message = "sorry,file is not exist";
            return "fileNotExist";
        }
        return "download";
    }    
    public InputStream getInputStream(){
        String dir = "/downloads/faq/"+fileName;
        return ServletActionContext.getServletContext().getResourceAsStream(dir);
    }


注解:

@Results({ 
    @Result(name = "download", type="stream",params={
            "contentType","application/octet-stream",
            "inputName","inputStream",
            "contentDisposition","attachment;filename=${fileName}",
            "bufferSize","4096"
            
    }),
    @Result(name="fileNotExist",location="/WEB-INF/web/FAQ.jsp")
})


jsp页面添加:

①<input type="hidden" value="${message}" id="message">


②<script type="text/javascript">
        $(document).ready(function(){
            var message = $("#message").val();
            if(message != null && message != ""){
                alert(message);
            }
        });

</script>


如果你要下载的文件名包含空格,比如: oracle 11g for windows.pdf

此程序就会有个小Bug,虽然点击下载后,会弹出下载框,但是,你看下载的文件名,却是oracle,空格后面的字符都没有了!当然,后面的文件类型名也没有。这样我们下载下来的文件却是一个未知文件!仔细查看原因,我们可以知道,在Action中接收到的 fileName的值是oracle 11g for windows.pdf,因为只有这里正常接收到下载文件名下载才能够成功,否则会提示文件没有找到。所以,问题出在注解那里。注解那里是这样写的filename=${fileName},我们将文件名替换掉${fileName},所以这里变为

filename=oracle 11g for windows.pdf,struts框架会将空格后面的字符过滤掉(推测),所以变为了

filename=oracle,这就是为什么我们下载文件的时候文件名仅仅显示oracle,为没有显示完全的原因。但我们前面又分析了,不能这样写:filename='${fileName}',因为这样写的话,我们下载的文件名就是'oracle 11g for windows.pdf' ,前后都有个单引号!如果你是在struts.xml中配置而不是用注解的形式配置,那么你最好这样写filename='${fileName}',这样就不会出问题。在注解中我们可以通过一个手段,将这个bug修复掉,那就是将空格用下划线"_"替换掉。修改后的代码如下:

public InputStream getInputStream()
    {
        String dir = "/downloads/faq/"+fileName;
       //特殊处理:如果下载的文件名称包含空格,那么需要将空格用下划线"_"替换掉
        //否则在注解那里filename=${fileName}得到的文件名仅仅是第一个空格的前一部分
        fileName = fileName.replace(' ','_');

        return ServletActionContext.getServletContext().getResourceAsStream(dir);
    }

现在即使你下载的文件名有空格,下载后也不会出现下载未知文件类型的文件了,bug已解决!

原创粉丝点击