mongodb - Load video from inputstream using java and video.js -


i fetch inputstream mongodb , pass video.js play.

it plays fine first time, once video finished , click on 'play' button play again got below exception in java code

java.net.socketexception: software caused connection abort: socket write error

my java code -

@requestmapping(value = "/getvideo/{videoid}" , method = requestmethod.get) public void fetchvideo(@pathvariable(value = "videoid") string videoid, httpservletresponse response, httpservletrequest request) {      try{         gridfsdbfile file = filestorageservice.getfilebyid(videoid);         file.getinputstream();          response.setheader("content-type", file.getcontenttype());         response.setheader("x-content-type-options", "nosniff");         response.setheader("accept-ranges", "bytes");          response.setcontentlength((int) file.getlength());         file.writeto(response.getoutputstream());          file.getinputstream().close();       } catch(exception e) {         e.printstacktrace();      } } 

html code -

<video id="galleryvideoid" class="hide-normal video-js vjs-default-skin vjs-big-play-centered" autoplay="autoplay" controls="controls" preload="auto" width="100%" height="100%" data-setup="{}">     <source th:src="@{'/getvideo/' + ${videoid} }" type='video/mp4'/> </video> 

i tried search on google , tried few solutions didn't work out.

please guide. thanks.

this same issue faced before , below exact solution of it. try below code :

import org.apache.commons.lang3.stringutils; import org.slf4j.logger; import org.slf4j.loggerfactory;  import javax.servlet.servletoutputstream; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.*; import java.nio.file.files; import java.nio.file.path; import java.nio.file.paths; import java.nio.file.attribute.filetime; import java.time.localdatetime; import java.time.zoneid; import java.time.zoneoffset; import java.util.arraylist; import java.util.arrays; import java.util.list;  /**  * see full code here : https://github.com/davinkevin/podcast-server/blob/d927d9b8cb9ea1268af74316cd20b7192ca92da7/src/main/java/lan/dk/podcastserver/utils/multipart/multipartfilesender.java  */ public class multipartfilesender {      protected final logger logger = loggerfactory.getlogger(this.getclass());      private static final int default_buffer_size = 20480; // ..bytes = 20kb.     private static final long default_expire_time = 604800000l; // ..ms = 1 week.     private static final string multipart_boundary = "multipart_byteranges";      path filepath;     httpservletrequest request;     httpservletresponse response;      public multipartfilesender() {     }      public static multipartfilesender frompath(path path) {         return new multipartfilesender().setfilepath(path);     }      public static multipartfilesender fromfile(file file) {         return new multipartfilesender().setfilepath(file.topath());     }      public static multipartfilesender fromuristring(string uri) {         return new multipartfilesender().setfilepath(paths.get(uri));     }      //** internal setter **//     private multipartfilesender setfilepath(path filepath) {         this.filepath = filepath;         return this;     }      public multipartfilesender with(httpservletrequest httprequest) {         request = httprequest;         return this;     }      public multipartfilesender with(httpservletresponse httpresponse) {         response = httpresponse;         return this;     }      public void serveresource() throws exception {         if (response == null || request == null) {             return;         }          if (!files.exists(filepath)) {             logger.error("file doesn't exist @ uri : {}", filepath.toabsolutepath().tostring());             response.senderror(httpservletresponse.sc_not_found);             return;         }          long length = files.size(filepath);         string filename = filepath.getfilename().tostring();         filetime lastmodifiedobj = files.getlastmodifiedtime(filepath);          if (stringutils.isempty(filename) || lastmodifiedobj == null) {             response.senderror(httpservletresponse.sc_internal_server_error);             return;         }         long lastmodified = localdatetime.ofinstant(lastmodifiedobj.toinstant(), zoneid.of(zoneoffset.systemdefault().getid())).toepochsecond(zoneoffset.utc);         string contenttype = "video/mp4";          // validate request headers caching ---------------------------------------------------          // if-none-match header should contain "*" or etag. if so, return 304.         string ifnonematch = request.getheader("if-none-match");         if (ifnonematch != null && httputils.matches(ifnonematch, filename)) {             response.setheader("etag", filename); // required in 304.             response.senderror(httpservletresponse.sc_not_modified);             return;         }          // if-modified-since header should greater lastmodified. if so, return 304.         // header ignored if if-none-match header specified.         long ifmodifiedsince = request.getdateheader("if-modified-since");         if (ifnonematch == null && ifmodifiedsince != -1 && ifmodifiedsince + 1000 > lastmodified) {             response.setheader("etag", filename); // required in 304.             response.senderror(httpservletresponse.sc_not_modified);             return;         }          // validate request headers resume ----------------------------------------------------          // if-match header should contain "*" or etag. if not, return 412.         string ifmatch = request.getheader("if-match");         if (ifmatch != null && !httputils.matches(ifmatch, filename)) {             response.senderror(httpservletresponse.sc_precondition_failed);             return;         }          // if-unmodified-since header should greater lastmodified. if not, return 412.         long ifunmodifiedsince = request.getdateheader("if-unmodified-since");         if (ifunmodifiedsince != -1 && ifunmodifiedsince + 1000 <= lastmodified) {             response.senderror(httpservletresponse.sc_precondition_failed);             return;         }          // validate , process range -------------------------------------------------------------          // prepare variables. full range represents complete file.         range full = new range(0, length - 1, length);         list<range> ranges = new arraylist<>();          // validate , process range , if-range headers.         string range = request.getheader("range");         if (range != null) {              // range header should match format "bytes=n-n,n-n,n-n...". if not, return 416.             if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {                 response.setheader("content-range", "bytes */" + length); // required in 416.                 response.senderror(httpservletresponse.sc_requested_range_not_satisfiable);                 return;             }              string ifrange = request.getheader("if-range");             if (ifrange != null && !ifrange.equals(filename)) {                 try {                     long ifrangetime = request.getdateheader("if-range"); // throws iae if invalid.                     if (ifrangetime != -1) {                         ranges.add(full);                     }                 } catch (illegalargumentexception ignore) {                     ranges.add(full);                 }             }              // if valid if-range header, process each part of byte range.             if (ranges.isempty()) {                 (string part : range.substring(6).split(",")) {                     // assuming file length of 100, following examples returns bytes at:                     // 50-80 (50 80), 40- (40 length=100), -20 (length-20=80 length=100).                     long start = range.sublong(part, 0, part.indexof("-"));                     long end = range.sublong(part, part.indexof("-") + 1, part.length());                      if (start == -1) {                         start = length - end;                         end = length - 1;                     } else if (end == -1 || end > length - 1) {                         end = length - 1;                     }                      // check if range syntactically valid. if not, return 416.                     if (start > end) {                         response.setheader("content-range", "bytes */" + length); // required in 416.                         response.senderror(httpservletresponse.sc_requested_range_not_satisfiable);                         return;                     }                      // add range.                                         ranges.add(new range(start, end, length));                 }             }         }          // prepare , initialize response --------------------------------------------------------          // content type file name , set content disposition.         string disposition = "inline";          // if content type unknown, set default value.         // content types, see: http://www.w3schools.com/media/media_mimeref.asp         // add new content types, add new mime-mapping entry in web.xml.         if (contenttype == null) {             contenttype = "application/octet-stream";         } else if (!contenttype.startswith("image")) {             // else, expect images, determine content disposition. if content type supported             // browser, set inline, else attachment pop 'save as' dialogue.             string accept = request.getheader("accept");             disposition = accept != null && httputils.accepts(accept, contenttype) ? "inline" : "attachment";         }         logger.debug("content-type : {}", contenttype);         // initialize response.         response.reset();         response.setbuffersize(default_buffer_size);         response.setheader("content-type", contenttype);         response.setheader("content-disposition", disposition + ";filename=\"" + filename + "\"");         logger.debug("content-disposition : {}", disposition);         response.setheader("accept-ranges", "bytes");         response.setheader("etag", filename);         response.setdateheader("last-modified", lastmodified);         response.setdateheader("expires", system.currenttimemillis() + default_expire_time);          // send requested file (part(s)) client ------------------------------------------------          // prepare streams.         try (inputstream input = new bufferedinputstream(files.newinputstream(filepath));              outputstream output = response.getoutputstream()) {              if (ranges.isempty() || ranges.get(0) == full) {                  // return full file.                 logger.info("return full file");                 response.setcontenttype(contenttype);                 response.setheader("content-range", "bytes " + full.start + "-" + full.end + "/" + full.total);                 response.setheader("content-length", string.valueof(full.length));                 range.copy(input, output, length, full.start, full.length);              } else if (ranges.size() == 1) {                  // return single part of file.                 range r = ranges.get(0);                 logger.info("return 1 part of file : ({}) ({})", r.start, r.end);                 response.setcontenttype(contenttype);                 response.setheader("content-range", "bytes " + r.start + "-" + r.end + "/" + r.total);                 response.setheader("content-length", string.valueof(r.length));                 response.setstatus(httpservletresponse.sc_partial_content); // 206.                  // copy single part range.                 range.copy(input, output, length, r.start, r.length);              } else {                  // return multiple parts of file.                 response.setcontenttype("multipart/byteranges; boundary=" + multipart_boundary);                 response.setstatus(httpservletresponse.sc_partial_content); // 206.                  // cast servletoutputstream easy println methods.                 servletoutputstream sos = (servletoutputstream) output;                  // copy multi part range.                 (range r : ranges) {                     logger.info("return multi part of file : ({}) ({})", r.start, r.end);                     // add multipart boundary , header fields every range.                     sos.println();                     sos.println("--" + multipart_boundary);                     sos.println("content-type: " + contenttype);                     sos.println("content-range: bytes " + r.start + "-" + r.end + "/" + r.total);                      // copy single part range of multi part range.                     range.copy(input, output, length, r.start, r.length);                 }                  // end multipart boundary.                 sos.println();                 sos.println("--" + multipart_boundary + "--");             }         }      }      private static class range {         long start;         long end;         long length;         long total;          /**          * construct byte range.          * @param start start of byte range.          * @param end end of byte range.          * @param total total length of byte source.          */         public range(long start, long end, long total) {             this.start = start;             this.end = end;             this.length = end - start + 1;             this.total = total;         }          public static long sublong(string value, int beginindex, int endindex) {             string substring = value.substring(beginindex, endindex);             return (substring.length() > 0) ? long.parselong(substring) : -1;         }          private static void copy(inputstream input, outputstream output, long inputsize, long start, long length) throws ioexception {             byte[] buffer = new byte[default_buffer_size];             int read;              if (inputsize == length) {                 // write full range.                 while ((read = input.read(buffer)) > 0) {                     output.write(buffer, 0, read);                     output.flush();                 }             } else {                 input.skip(start);                 long toread = length;                  while ((read = input.read(buffer)) > 0) {                     if ((toread -= read) > 0) {                         output.write(buffer, 0, read);                         output.flush();                     } else {                         output.write(buffer, 0, (int) toread + read);                         output.flush();                         break;                     }                 }             }         }     }     private static class httputils {          /**          * returns true if given accept header accepts given value.          * @param acceptheader accept header.          * @param toaccept value accepted.          * @return true if given accept header accepts given value.          */         public static boolean accepts(string acceptheader, string toaccept) {             string[] acceptvalues = acceptheader.split("\\s*(,|;)\\s*");             arrays.sort(acceptvalues);              return arrays.binarysearch(acceptvalues, toaccept) > -1                     || arrays.binarysearch(acceptvalues, toaccept.replaceall("/.*$", "/*")) > -1                     || arrays.binarysearch(acceptvalues, "*/*") > -1;         }          /**          * returns true if given match header matches given value.          * @param matchheader match header.          * @param tomatch value matched.          * @return true if given match header matches given value.          */         public static boolean matches(string matchheader, string tomatch) {             string[] matchvalues = matchheader.split("\\s*,\\s*");             arrays.sort(matchvalues);             return arrays.binarysearch(matchvalues, tomatch) > -1                     || arrays.binarysearch(matchvalues, "*") > -1;         }     } } 

try surely compatible case. thank you.


Comments

Popular posts from this blog

javascript - Karma not able to start PhantomJS on Windows - Error: spawn UNKNOWN -

c# - Display ASPX Popup control in RowDeleteing Event (ASPX Gridview) -

Nuget pack csproj using nuspec -