[产生背景]
刚一开使用renderFile(file);前端使用audio标签播放,播放时后台总是出现异常
前台audio标签
<audio id="audioPlay" src="/litongjava-windows-tts/tts?text=很多文本"></audio>
后台异常
九月 06, 2020 10:16:50 上午 com.jfinal.core.ActionHandler error 严重: /tts?text=省略内容 com.jfinal.render.RenderException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。 at com.jfinal.render.FileRender.rangeRender(FileRender.java:244) at com.jfinal.render.FileRender.render(FileRender.java:123) at com.jfinal.core.ActionHandler.handle(ActionHandler.java:111) at com.litong.jfinal.handler.ActionSuffixHandler.handle(ActionSuffixHandler.java:28) at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:90) at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132) at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:119) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376) at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
请求返回的状态码,并且点击一次播放按钮,播放了3次
异常的具体原因我没有找到,但是我认为和renderFile默认弹出下载框有关系
[解决思路]
自定义的一个render,读取文件流,输出到response
controller调用
render(new InputStreamRender(file));
render代码
package com.litong.jfinal.render; import java.io.File; import java.io.IOException; import com.jfinal.render.Render; import com.litong.utils.io.StreamUtils; /** * @author bill robot * @date 2020年9月6日_上午9:56:51 * @version 1.0 * @desc */ public class InputStreamRender extends Render { private File srcfile; public InputStreamRender(File srcfile) { this.srcfile = srcfile; } @Override public void render() { if (srcfile != null) { try { StreamUtils.copy(srcfile, response.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } } }
工具类
package com.litong.utils.io; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * @author bill robot * @date 2020年8月22日_上午1:08:25 * @version 1.0 * @desc */ public class StreamUtils { public static final int BUFFER_SIZE = 4096; public static int copy(InputStream in, OutputStream out) throws IOException{ int byteCount = 0; byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead = -1; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); byteCount += bytesRead; } return byteCount; } public static void copy(File file, OutputStream outputStream) { FileInputStream fileInputStream=null; try { fileInputStream = new FileInputStream(file); copy(fileInputStream, outputStream); } catch (IOException e) { e.printStackTrace(); }finally { IOUtils.closeQuietly(fileInputStream); } } }
再次测试,可以返回200