
本文探讨vaadin 8应用在处理大型音频文件(尤其超过7mb)时,执行定位操作可能遇到的`java.io.ioexception: a connection established by software on your host computer has been dropped`错误。核心问题在于vaadin 8内置audio组件的全文件加载机制。文章推荐使用支持范围请求的`audiovideo`组件,以实现高效流式播放和定位,并提供服务器配置调整作为次要方案。
在Vaadin 8应用程序中,当尝试对大型音频文件(例如超过7MB)执行定位(seek)操作时,可能会遇到java.io.IOException: Se ha anulado una conexión establecida por el software en su equipo host.(A connection established by software on your host computer has been dropped)异常。该异常通常伴随着服务器日志中sun.nio.ch.SocketDispatcher.writev0、io.undertow.server.protocol.http.HttpResponseConduit.write以及Vaadin内部DownloadStream.writeResponse等堆栈信息,表明在向客户端写入HTTP响应流时发生了连接中断。
导致此问题的核心原因在于Vaadin 8内置的Audio组件设计相对简单。它倾向于一次性加载整个音频文件到内存并尝试通过HTTP响应发送给客户端。对于小文件而言,这通常不是问题。然而,当音频文件体积较大时,这种全文件加载和传输机制会引发以下挑战:
原始代码片段中的seekAudio方法通过JavaScript直接操作HTML <audio> 元素的currentTime属性,并强制调用load()方法。load()方法会指示浏览器重新加载媒体资源,如果服务器没有正确处理HTTP范围请求(Range Requests),这实际上可能导致重新尝试下载整个文件,从而再次触发上述IOException。
private synchronized void seekAudio(double secs, String id) {
// 强制重新加载,这可能导致浏览器重新请求整个文件
Page.getCurrent().getJavaScript().execute("document.getElementById('" + id + "').load();");
// 设置播放时间
Page.getCurrent().getJavaScript().execute("document.getElementById('" + id + "').currentTime = " + secs + ";");
// 设置播放速度
Page.getCurrent().getJavaScript().execute("document.getElementById('" + id + "').playbackRate = " + speed + ";");
}解决大型媒体文件播放和定位问题的最佳实践是利用HTTP协议的范围请求(Range Requests)功能,也称为HTTP Partial Content (RFC 7233)。这允许客户端(浏览器)仅请求文件的一部分内容,而不是整个文件。当用户进行定位操作时,浏览器可以发送一个范围请求,只获取从新定位点开始的一小段数据,从而大大提高效率和响应速度。
Vaadin Directory中提供了一个名为AudioVideo的组件,它是Vaadin 8内置Audio和Video组件的增强替代品。AudioVideo组件支持范围请求,能够有效地处理大型媒体文件。
首先,需要将AudioVideo组件添加到您的Vaadin项目中。通常通过Maven或Gradle依赖引入:
<!-- Maven 示例 -->
<dependency>
<groupId>org.vaadin.addons</groupId>
<artifactId>audiovideo</artifactId>
<version>2.0.0</version> <!-- 请检查Vaadin Directory获取最新兼容版本 -->
</groupId>在您的Vaadin UI代码中,用AudioVideo替代原有的Audio组件:
import org.vaadin.addons.audiovideo.Audio; // 注意:这是addon的Audio,不是com.vaadin.ui.Audio
public class MyAudioPlayer extends VerticalLayout {
private Audio audioPlayer;
private StreamResource audioResource; // 假设您的音频文件是一个StreamResource
public MyAudioPlayer(String audioFileName, StreamResource audioStreamResource) {
// 创建StreamResource,假设您已经有了获取InputStreamProvider的逻辑
// StreamResource audioStreamResource = new StreamResource(new StreamResource.StreamSource() {
// @Override
// public InputStream getStream() {
// // 返回音频文件的InputStream
// return getClass().getResourceAsStream("/" + audioFileName);
// }
// }, audioFileName);
this.audioResource = audioStreamResource;
// 创建AudioVideo组件的Audio实例
audioPlayer = new Audio();
audioPlayer.setSource(audioResource);
audioPlayer.setAutoplay(false);
audioPlayer.setControls(true); // 显示播放控制条
audioPlayer.setWidth("100%");
addComponent(audioPlayer);
// 如果需要程序化定位,可以直接调用组件的API
// 注意:AudioVideo组件内部会处理范围请求,通常不需要手动调用JS的load()或currentTime
// 但如果需要监听事件或执行更复杂的JS操作,可以继续使用Page.getCurrent().getJavaScript().execute()
Button seekButton = new Button("定位到10秒", event -> {
// AudioVideo组件可能提供更高级的API来控制播放,或者仍然可以通过JS操作
// 例如,直接设置currentTime
Page.getCurrent().getJavaScript().execute(
"document.getElementById('" + audioPlayer.getId() + "').currentTime = 10;"
);
});
addComponent(seekButton);
}
}使用AudioVideo组件后,当浏览器发送范围请求时,AudioVideo组件内部会正确地处理这些请求,只从StreamResource中读取请求的字节范围并返回,从而避免了全文件加载导致的IOException。
如果由于某种原因无法使用AudioVideo组件,或者您的应用程序需要处理非常大的文件,并且您确定问题确实是服务器端对文件大小的限制,那么可以尝试调整应用服务器或Servlet容器的配置。
注意事项:
以下是一些常见服务器的配置示例:
对于WildFly或JBoss EAP,其内置的Web服务器是Undertow。您可能需要调整undertow子系统中的相关配置,例如:
通常通过WildFly管理控制台或standalone.xml/domain.xml文件进行配置。例如,增加buffer-size:
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" buffer-pool="default" worker="default" enable-http2="true" buffer-size="65536"/>
<!-- ... 其他配置 ... -->
</server>对于Tomcat,可能需要修改server.xml文件中的Connector配置:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxPostSize="0" <!-- 设置为0表示无限制,不推荐,应设置一个合理的大值 -->
maxHttpHeaderSize="65536" />如果您的Vaadin应用部署在Nginx等反向代理之后,Nginx也可能存在大文件传输的限制:
http {
# ...
client_max_body_size 50m; # 允许最大50MB的请求体
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_read_timeout 300s; # 增加读取超时时间
# ...
}处理Vaadin 8中大型音频文件的播放和定位问题,核心在于理解HTTP协议的特性和Vaadin组件的设计。
通过选择正确的组件和理解底层机制,您可以构建出更健壮、性能更优的Vaadin应用程序,即使面对大型媒体文件也能提供流畅的用户体验。
以上就是Vaadin 8应用中大型音频文件播放与定位时的IOException解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号