RequestDispatcher.forward到媒体文件?

3
我最近遇到了一个需要解决的问题,找到了一个解决方案,但如果我可以使用RequestDispatcher.forward将请求转发到媒体URL,那么这个解决方案可能会大大简化。
从文档中得知,它只支持servlet、JSP文件或HTML文件。我尝试了一下媒体URL,它没有抱怨,但它没有返回正确的头信息(例如mime类型),也许还有其他错误,总之它没有像预期的那样工作。 是否有一种方法可以使用RequestDispatcher.forward与媒体URL一起使用,以便响应与直接向Web服务器请求媒体URL时完全相同? 编辑: 我可以证实至少Content-Type是正确的,因为对于任何媒体文件,它都返回Content-Type text/html; charset=iso-8859-1。此外,我尝试直接在Windows Media Player中打开URL,似乎会在开始播放之前下载整个视频,这是不可接受的。因此,我可以安全地假设forward并没有将控制权正确地交还给IIS,或者至少对于媒体文件是这样。

1
除了 MIME 类型之外,标头有什么不同? - Leigh
@Leigh,我需要检查一下。如果我有足够的时间,明天我会看一下。 - plalx
也许你可以用不同的方式来解决这个问题。你最初的问题是能够控制谁可以访问这些视频文件以及何时可以访问这些视频文件吗?IIS可以正确地为您处理这些文件的服务,但您无法仅使用IIS设置所需的限制。对吧?在您的用户和网站之间是否有任何其他设备/软件可供利用?负载均衡器、代理服务器等,在某些时间可能能够限制流量。用户限制部分可以由IIS(假设活动目录)处理。 - Miguel-F
@Miguel-F 很遗憾,我没有其他可控制的事情,而且必须通过ColdFusion完成,因为用户在线租用视频的收听权利,针对特定的时间段,所以我必须使用特定应用程序逻辑来执行限制。我想到的唯一其他解决方案是动态更改文件的NTFS权限,但我真的不喜欢这个解决方案。 我很惊讶居然没有内置机制来委托请求。我设计的解决方案有效,但它也有缺点,例如必须使用匿名身份验证。 - plalx
感谢澄清。我需要再考虑一下这个问题。你看到Ben Nadel的这篇文章了吗?使用ColdFusion和MOD XSendFile高效地流式传输安全文件。虽然它涉及Apache模块XSendFile,但他还提到“有办法在IIS中运行Apache配置(例如Helicon Ape)”。如果你还没有看过这篇文章,你可能想去看看。他总是有很好的详细信息。我刚刚看到你已经评论过了。 - Miguel-F
@Miguel-F 是的,那本来是个好主意,但很不幸我不能安装任何未经批准的插件/模块/扩展。我想我可以尝试通过编写自己的IIS模块来解决这个问题。 - plalx
1个回答

2
你找到的解决方案指向了正确的方向,但是我对ColdFusion一无所知,但是使用Servlets同样可以轻松完成相同的事情。
如果你想使用RequestDispatcher.forward方法,那么你可以在forward方法中指定一个servlet url。然后在那个servlet中,你只需要读取媒体并使用OutputStream作为响应发送即可。
例如:
在你的servlet的doGet或doPost方法中,你只需要根据你的媒体类型设置内容类型,读取并发送它即可。
下面是一个简单的例子,你可以用它来从servlet发送媒体作为响应:
public void doGet(HttpServletRequest request, HttpServletResponse response)  {
    response.setContentType("video/x-ms-wmx");
    ServletContext ctx = getServletContext();

    InputStream is = ctx.getResourceAsStream("/path/to/media/file");

    int read = 0;
    byte bytes[] = new byte[1024];

    OutputStream os = response.getOutputStream();
    while((read = is.read(bytes)) != -1) {
        os.write(bytes, 0, read);
    }
    os.flush();
    os.close();
}

@plalx:我认为请求来自哪里并不重要。我认为头部在此过程中不会改变,即使它们发生改变,也会根据响应内容进行更改。此外,Windows Media Player应该能够处理媒体的响应。 - me_digvijay
你不应该关闭 HttpServletResponse 的 OutputStream(或 PrintWriter)。这是容器的责任(flush() 是可以的)。 - lance-java
不,Servlet容器(例如Tomcat/Jetty)负责创建和关闭响应的OutputStream或Writer。如果您close()它,当尝试close()已经关闭的流/写入器时,容器可能会抛出异常。 - lance-java
@uklance:没错,但是这个outputstream是由我显式创建的,而不是容器创建的。所以关闭它应该是我的责任。如果我没有打开它,那么让它保持原样对我来说更有意义。 - me_digvijay
不,它是由容器创建的。你只是对它进行了get操作。尝试使用过滤器包装响应,在调用close()时记录日志。在你的代码中,你会看到2个日志语句。 - lance-java
显示剩余7条评论

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