使用GWT下载动态文件

9

我有一个GWT页面,用户可以输入数据(开始日期,结束日期等),然后通过RPC调用将这些数据发送到服务器。在服务器上,我想使用POI生成Excel报告,并让用户在本地计算机上保存该文件。

这是我的测试代码,用于将文件流传回客户端,但出于某种原因,我认为它不知道如何在使用RPC时将文件流传输到客户端:

public class ReportsServiceImpl extends RemoteServiceServlet implements ReportsService {
    public String myMethod(String s) {

        File f = new File("/excelTestFile.xls");

        String filename = f.getName();

        int length = 0;

        try {
            HttpServletResponse resp = getThreadLocalResponse();
            ServletOutputStream op = resp.getOutputStream();
            ServletContext context = getServletConfig().getServletContext();
            resp.setContentType("application/octet-stream");
            resp.setContentLength((int) f.length());
            resp.setHeader("Content-Disposition", "attachment; filename*=\"utf-8''" + filename + "");

            byte[] bbuf = new byte[1024];
            DataInputStream in = new DataInputStream(new FileInputStream(f));

            while ((in != null) && ((length = in.read(bbuf)) != -1)) {
                op.write(bbuf, 0, length);
            }

            in.close();
            op.flush();
            op.close();

        }
        catch (Exception ex) {
            ex.printStackTrace();
        }

        return "Server says: " + filename;
    }
}

我在互联网上读到过一个说法,即无法使用RPC进行文件流操作,必须使用Servlet。是否有关于如何使用Servlet以及如何从ReportsServiceImpl中调用该Servlet的示例?我真的需要创建一个Servlet吗,还是可以通过我的RPC将其流回来?


请详细阐述问题。"它不知道"并不是一个具体的描述。到底发生了什么?到底没有发生什么? - BalusC
1
@sri的回答很有道理。现在轮到我发表一些评论了:1)DataInputStream是多余的。只需使用直接的FileInputStream即可。毕竟,您需要在InputStream类中定义的read()方法。2)in!= null检查也是多余的,因为它永远不会为空(您使用new创建了一个新的对象,它永远不会为空)。3)Content-Disposition头在filename部分看起来格式不正确。要获取有关如何进行基本文件服务的一些想法,您可能会发现此文章有用。祝你好运。 - BalusC
3个回答

14
你需要制作一个普通的Servlet,不能ReportsServiceImpl中传输二进制数据。此外,没有办法从ReportsServiceImpl调用servlet-你的客户端代码必须直接调用servlet。
在客户端,你需要创建一个包含参数的正常锚链接,通过查询字符串传递参数。例如:<a href="http://myserver.com/myservlet?parm1=value1&.."</a>
在服务端,将代码移动到标准的Servlet中,该Servlet不继承自RemoteServiceServlet。从请求对象中读取参数,创建Excel并将其发送回客户端。浏览器将自动弹出文件下载对话框。

2
您可以使用 GWT RPC 和 数据 URI 来实现这一点:
  1. 在您的示例中,使您的 myMethod 返回文件内容。
  2. 在客户端上,使用接收到的文件内容格式化 数据 URI
  3. 使用 Window.open 打开文件保存对话框,并传递格式化的 数据 URI
请参阅此参考文献,了解 数据 URI 的用法:

在 jQuery 中导出为 CSV


1
需要考虑到DATA URIs 在IE6和7上不被支持。IE8有部分支持。 - codingscientist

0

通过RPC渠道,有多种方法可以获取所需的二进制数据...例如uuencode。但是,您仍然需要让浏览器将文件处理为下载。

基于您的代码,看起来您正在尝试通过修改服务器响应以便浏览器将其识别为下载(例如打开保存对话框),从而触发处理给定MIME类型的标准浏览器机制。要做到这一点,您需要让浏览器代表您发出请求,并且需要在那里的servlet处理请求。可以使用rest url来完成,但最终即使那样,您也需要一个serviet来处理。

实际上,您需要将浏览器窗口URL设置为发送修改后的响应对象的URL。

因此,这个关于流式传输的问题与代码示例并不真正兼容。必须调整通信协议或服务器修改响应对象中的一个。

最容易调整的是通信方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接