###前提・実現したいこと
Struts2で動画をサーバから取得し、動的にvideoタグを生成してそこにソースを当て込み動画を再生させています。
PCからは問題なく閲覧できていますが、スマートフォンやタブレットでは閲覧できない場合があるため、これを解決させたいです。現在iphone、Androidともに再生できていません。
https://teratail.com/questions/85991
の質問とほぼ同じなのですが、問題の箇所が絞り込めたため再度投稿させていただきました。
動画ファイルはmp4でH.264形式です。ファイルサイズは約4MBです。
動画ファイルのパスを隠すため、JSPではActionクラスを呼び、そこでパスを探しています。
###発生している問題・エラーメッセージ
iphone5Sで動画を再生させようとすると、https://teratail.com/questions/85991の現象が発生します。
また、サーバ側でリクエスト後に以下のメッセージが表示されます。
重大: Exception occurred during processing request: java.io.IOException: 確立された接続がホスト コンピューターのソウトウェアによって中止されました。 [月 8 28 16:19:18 JST 2017]
###該当のソースコード
videoタグのsrcで指定するActionクラスです。
VideoAction.java
1package action; 2import 省略; 3@Namespace("/") 4@ParentPackage("test") 5@Results({ 6 @Result(name = "video", type = "stream", 7 params = { 8 "inputName", "inputStream", 9 "contentType", "video/mp4", 10 "contentLength", "${contentLength}", 11 "contentDisposition", "attachment; filename = ${fileName}" 12 }), 13 @Result( name="error" , type="dispatcher", location="/error.jsp") 14}) 15public class VideoAction extends ActionSupport { 16 private InputStream inputStream; 17 private long contentLength; 18 private String fileName; 19 private String lotNo; 20 private String reqFilePath; 21 22 public String execute() { 23 String lotDir = "/test/"; 24 BufferedInputStream bis = null; 25 26 try { 27 File lotNoFile = new File(lotDir + this.lotNo); 28 bis = new BufferedInputStream(new FileInputStream(lotNoFile)); 29 30 byte[] byteArray = IOUtils.toByteArray(bis); 31 this.inputStream = new ByteArrayInputStream(byteArray); 32 this.contentLength = byteArray.length; 33 34 return "video"; 35 } catch (Exception e) { 36 return "error"; 37 } finally { 38 try { 39 bis.close(); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 44 } 45 } 46 47 public InputStream getInputStream() { 48 return inputStream; 49 } 50 public void setInputStream(InputStream inputStream) { 51 this.inputStream = inputStream; 52 } 53 public long getContentLength() { 54 return contentLength; 55 } 56 public void setContentLength(long contentLength) { 57 this.contentLength = contentLength; 58 } 59 public String getFileName() { 60 return fileName; 61 } 62 public void setFileName(String fileName) { 63 this.fileName = fileName; 64 } 65 public String getLotNo() { 66 return lotNo; 67 } 68 public void setLotNo(String lotNo) { 69 this.lotNo = lotNo; 70 } 71 public String getFilePath() { 72 return reqFilePath; 73 } 74 public void setFilePath(String filePath) { 75 this.reqFilePath = filePath; 76 } 77}
video.jsp
1<video src='video.action?lotNo=1></video>
###試したこと
動画ファイルに問題があるかと思い調査しましたが、プロジェクトのルートディレクトリ以下に直接mp4ファイルを配置し、ソースにパスを直書きしたらiphoneで動画が再生できたため、動画の問題ではないと思います。
###補足情報(言語/FW/ツール等のバージョンなど)
Struts2.3.24
VideoAction.javaのResult又はStreamの指定に問題があるのではと思っています。
情報に不足などありましたらご指摘ください。よろしくお願いします。
###追記
othersight様、A-pZ様
時間が空いてしまい申し訳ありません。
https://www.stevesouders.com/blog/2013/04/21/html5-video-bytes-on-ios/
等を参考に、レスポンスヘッダにAccept-Range、Content-Rangeを仕込み、Content-LengthはリクエストヘッダのRangeが0-1だった場合は2を返すなど行いましたが、未だ解決に至っていません。
ソースは以下になります。
VideoAction.java
1HttpServletRequest request = getRequest(); //リクエストヘッダを取得 2String range = request.getHeader("Range").replace("bytes=", ""); 3String rangeFirst = range.substring(0, range.indexOf("-")); 4String rangeLast = range.substring(range.indexOf("-") + 1, range.length()); 5String contentRange = ""; 6 7HttpServletResponse response = getResponse(); 8response.setStatus(206); 9response.setHeader("Accept-Ranges", "bytes"); 10 11//range: "0-" 12if (range.equals("0-")) { 13contentRange = "bytes " + rangeFirst + "-" + (Integer.parseInt(rangeFirst) + 1) + "/" + this.contentLength; 14} 15//range: "0-x" 16if (range.indexOf("0-") != -1 && (!rangeLast.isEmpty() && !rangeLast.equals("0"))) { 17contentRange = "bytes " + rangeFirst + "-" + rangeLast + "/" + this.contentLength; 18} 19//range: "x-" 20if (!rangeFirst.equals("0") && range.lastIndexOf("-") != -1) { 21contentRange = "bytes " + rangeFirst + "-" + String.valueOf(this.contentLength - 1) + "/" + this.contentLength; 22} 23//range: "0-1" 24if (range.equals("0-1")) { 25contentRange = "bytes 0-1/" + this.contentLength; 26this.contentLength = 2; 27} 28//range: "x-x" 29if (!rangeFirst.equals("0") && range.lastIndexOf("-") == -1) { 30contentRange = "bytes " + rangeFirst + "-" + (Integer.parseInt(rangeLast) + 1) + "/" + this.contentLength; 31this.contentLength = 2; 32} 33 34response.setHeader("Content-Range", contentRange); 35System.out.println("★レスポンスRange--- " + contentRange); 36System.out.println("★コンテントLength--- " + this.contentLength); 37
上記のソースを仕込み、1回目のリクエストに対しては正常に動作しましたが2回目のリクエストからはサーバ側で
重大: Exception occurred during processing request: java.io.IOException: 確立された接続がホスト コンピューターのソウトウェアによって中止されました。 [月 8 28 16:19:18 JST 2017]
がまた発生してしまいます。
Last-ModifiedやEtagなど仕込むことも試しましたが、変わらないようです。
以下リクエスト、レスポンスになります。
1回目のリクエスト Accept:*/* Accept-Encoding:identity;q=1, *;q=0 Accept-Language:ja,en-US;q=0.8,en;q=0.6 Cache-Control:no-cache Connection:keep-alive Cookie:JSESSIONID=0D946AEE3ABF37850218436884DEB391; _ga=GA1.1.2024693826.1504524761; _gid=GA1.1.353248483.1504524761 Host:localhost:8080 Pragma:no-cache Range:bytes=0- Referer:http://localhost:8080/test/test.action User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
1回目のレスポンス Accept-Ranges:bytes Connection:Keep-Alive Content-Disposition:attachment; filename = Content-Language:ja Content-Length:1595162 Content-Range:bytes 0-1/1595162 Content-Type:video/mp4 Date:Tue, 05 Sep 2017 06:35:37 GMT Etag:42b795-4867d5fcac1c0 Server:Apache-Coyote/1.1
2回目のリクエスト Accept:*/* Accept-Encoding:identity;q=1, *;q=0 Accept-Language:ja,en-US;q=0.8,en;q=0.6 Cache-Control:no-cache Connection:keep-alive Cookie:JSESSIONID=0D946AEE3ABF37850218436884DEB391; _ga=GA1.1.2024693826.1504524761; _gid=GA1.1.353248483.1504524761 Host:localhost:8080 Pragma:no-cache Range:bytes=1572864- Referer:http://localhost:8080/test/test.action User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
2回目のレスポンス Accept-Ranges:bytes Connection:Keep-Alive Content-Disposition:attachment; filename = Content-Language:ja Content-Length:1595162 Content-Range:bytes 1572864-1595161/1595162 Content-Type:video/mp4 Date:Tue, 05 Sep 2017 06:35:37 GMT Etag:42b795-4867d5fcac1c0 Server:Apache-Coyote/1.1
すみませんが、何かわかることがありましたらご教授いただけますでしょうか。
よろしくお願いいたします。
![guest](/img/icon/icnUserSample.jpg)
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。