简体   繁体   中英

Transfer large video files from Tomcat server over HTTP to Android client

I have looked at all of the similar questions but none of the answers seem to solve the problem for me. I am trying to stream a video file from my Tomcat server to an android web browser. I am able to stream the video in the Chrome browser. I am also able to transfer image (smaller files) using a similar code.

Here is my code for the servlet which converts the video into a bytestream to transfer it over HTTP

public class VideoServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    try {
        File file = new File("C:\\Users\\ishan\\Desktop\\hisocData\\"
                + req.getPathInfo().substring(1));

        FileInputStream is = new FileInputStream(file);

        resp.setHeader("Content-Length", Long.toString(file.length()));
        resp.setContentType("video/3gpp");

        // Open the file and output streams
        OutputStream out = resp.getOutputStream();

        // Copy the contents of the file to the output stream
        byte[] buf = new byte[1024];
        int count = 0, length = 0;
        while ((count = is.read(buf)) >= 0) {
            out.write(buf, 0, count);
            length += count;
        }
        is.close();
        out.close();
        resp.setContentLength(length);
    } catch (FileNotFoundException e) {
        OutputStream out = resp.getOutputStream();
        out.write("File not found!".getBytes());
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

I am getting this error when I try to access this video file on the Android web browser:

ClientAbortException:  java.net.SocketException: Connection reset by peer: socket write error
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:388)
    at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:462)
    at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:413)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:401)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:91)
    at data.VideoServlet.doGet(VideoServlet.java:40)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.net.SocketException: Connection reset by peer: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(Unknown Source)
    at java.net.SocketOutputStream.write(Unknown Source)
    at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
    at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:462)
    at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:366)
    at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:240)
    at org.apache.coyote.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:84)
    at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:192)
    at org.apache.coyote.Response.doWrite(Response.java:504)
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:383)

I would really appreciate your help. I have been stuck on this problem for a few days now.

You need to implement HTTP range support. See this , nearly identical question/answer.

The problem is very likely to be caused by an attempt to set content-length after the response has already been sent. You should remove this line

resp.setContentLength(length);

Please note that it is equivalent to the one you did in the beginning of request:

resp.setHeader("Content-Length", Long.toString(file.length()));

I would suggest you to replace resp.setHeader(...) with resp.setContentLength(file.length());

The problem was I was trying to transfer video in .3gp format which was not recognized by the players. When I changed it to .mov it worked perfectly. Sorry for the trouble guys,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM