我想将文件压缩成流(ZipOutPutStream),不生成临时文件,然后下载到客户端。
而struts2的下载是用的InputStream,请问如何进行转换?或者有别的方法。我以前用Servlet实现过将文件将数据生成ServletOutPutStream然后下载,不知道用Struts2能不能实现,谢谢!

解决方案 »

  1.   

    不生成临时文件啊... 确实有点难啊.
    你利用 ZipOutPutStream 动态生成压缩文件,直接写到客户端, 而 Struts2 的 ResultType 是不好修改源代码, 那么你可以 自定义一个 Interceptor, 然后根据文件的 ContentType 类型判断是否是输出 压缩文件,然后在 Interceptor 的逆回阶段(actionInvocation.invoke()方法之后) 作一些处理;这是我的想法,但是没有实践....
      

  2.   

    文件压缩成流(ZipOutPutStream),不生成临时文件,然后下载到客户端。
    那你就是想把ZipOutPutStream直接放在response中输出到客户端,把ZipOutPutStream输出流写入到InputStream流中。看看InputStream stream = null;
    ZipOutPutStream bos = null;
    try {
    stream = file.getInputStream();
    bos = new FileOutputStream(filePath);
    int bytesRead = 0;
    byte[] buffer = new byte[1024];
    while ((bytesRead = stream.read(buffer, 0, buffer.length)) != -1){
        bos.write(buffer, 0, bytesRead);//
    }           
    } finally {
    if(bos != null){
    try {
    bos.close();
    } finally {
    if(stream != null){
    stream.close();
    }
    }
    }
    }
      

  3.   

    to Purking : 
    谢谢,请问你的意思是不是在Action执行后,调用生成ZipOutPutStream的方法,输出到客户端。to warison2008 : 
    谢谢,不过,我觉得这段应该是将文件转换成输出流。
      

  4.   

    http://www.bitscn.com/wap.php?action=article&id=145718
    看看这个 
      

  5.   

    to zl3450341 : 
    谢谢,这个好像是教程上的,貌似一模一样。
    struts2有没有下载输出流的方式?
    请大家帮帮忙,谢谢了。
      

  6.   

    刚看到一种方式可以解决临时文件的问题,就是在execute方法中return null;
    这样就可以在servlet上下文中取到HttpServletResponse,用servlet的方法将输出流传到客户端。不过还是希望能有struts2的方法!
      

  7.   


    恩,对于 Struts2 来说,其有一个 ResultType 为 Stream Result 的类型,他直接获取 InputStream 输入流,可以想象他是做了些事情才返回给客户端的, 那么这样很明显无法满足你的需求,你需要直接利用 ZipOutPutStream 输出给客户端,并且是没有临时文件的,所以无法使用到 Struts2 提供的 Stream Result 返回类型,所以得用自己的解决方案..我的想法很直接, 就是利用 Interceptor 来解决这个问题,但不是在请求进入的阶段,而是请求出来的阶段,使用这个就要解决两个问题,第一个如何让 Action 进入这个 Interceptor; 第二个,如何在 Interceptor 中拿到你动态生成的 ZipOutPutStream;
    第一个问题: 这个比较好解决, 对这个 Action 的 <interceptors> 进行特殊配置就可以了,一个专门为这一个 Action 作用的 Interceptor;
    第二个问题: 这个可以利用 Struts2 的 OGNL 中的 ValueStack 来解决,在 Action 中利用 ActionContext 拿到 ValueStack 将 ZipOutputStream 保存在其中,然后返回一个普通返回类型(后面会有解释); 当进入 Interceptor 以后,你可以借助 ActionInvocation 来获取 ValueStack 从而获得到 ZipOutputStream, 然后在 Interceptor 中利用 ActinoContext 或得 HttpServletResponse 将 ZipOutputStream 写回客户端;补充: 为什么可以算便返回一个试图类型呢? 可以查看下其文档当中的  Big Picture 一章, Interceptor 的逆回阶段是在 Result 之后,也就是说在 Interceptor 中操作 HttpServletResponse 可以将前面的覆盖掉,所以这样做了;由于你说需要 Struts2 的解决方法,所以使用了 ValueStack 传递数据,当然也可使用其他作用域例如 Session,毕竟ActionContext 由于使用thread local实现所以在任何地方都可以随意获取;这只是一个思路,其实你将 execute方法中return null; 也是一样的,只是将我这个思路的向客户端写数据的操作提前了而已;
      

  8.   

    至于这么麻烦吗?
    配置一个action:
          <action name="export" class="co.dnl.editor.action.ExportAction">
    <result name="success" type="stream">
    <!-- param name="contentType">application/zip</param-->
    <param name="contentType">application/zip</param>
    <param name="inputName">inputStream</param>
    <param name="contentDisposition">
    filename="mycontent.zip"
    </param>
    <param name="bufferSize">1024</param>
    </result>
          </action>
    写一个action, 确保有inputStream变量:
    public class ExportAction extends BaseAction 
    {
    private InputStream inputStream;

        public String execute() 
        {
         log.info("in ExportAction");
         String str = "hello, world. I am from struts2 output";
         inputStream = new ByteArrayInputStream(str.getBytes());     return Action.SUCCESS;
        } public InputStream getInputStream() {
    return inputStream;
    } public void setInputStream(InputStream inputStream) {
    this.inputStream = inputStream;
    }
        
        
    }
    访问: http://localhost:8080/yourApp/export.action
    导出下载了。
    over