0

我有一個工作代碼庫,它服務於包裝在HTTP狀態206中的Chunks<byte[]>。代碼將.mp3文件傳輸到瀏覽器。如何在Play Framework(Java)v2.4.x中爲反應性字節塊提供服務

public class ChunksController extends Controller { 

    private static byte[] song; 
    private static RangeWrapper range; 
    private static Chunks<byte[]> chunks; 

    @With(MP3Headers.class) 
    public static F.Promise<Result> handler() { 
     return F.Promise.promise(new Function0<Result>() { 
      public Result apply() throws Throwable { 

       // Now we are serving a Promise of a Result 
       // Is there a way to serve a Promise of Chunks<byte[]>? 

       song = Files.readAllBytes(Paths.get("public/mp3/song.mp3")); 
       range = new RangeWrapper(request().getHeader("Range"), song.length); 

       chunks = new ByteChunks() { 
        public void onReady(Chunks.Out<byte[]> out) { 
         out.write(Arrays.copyOfRange(song, range.getFrom(), range.getTo())); 
         out.close(); 
        } 
       }; 

       // Set response headers so that the browser knows the content 
       response().setHeader("Content-Range", String.format("bytes %d-%d/%d", range.getFrom(), range.getTo(), song.length)); 
       response().setHeader("X-Content-Length", Integer.toString(range.getContentLength())); 
       response().setHeader("Content-Length", Integer.toString(range.getContentLength())); 

       // I am very much wondering if this is the blocking part of the program... 
       return status(206, chunks); 
      } 
     }); 
    } 
} 

在代碼示例中,MP3HeadersRangeWrapper是便利類,定義如下。

public class MP3Headers extends Action.Simple { 

    public F.Promise<Result> call(Http.Context ctx) throws Throwable { 
     ctx.response().setContentType("audio/mpeg"); 
     ctx.response().setHeader("Accept-Ranges", "bytes"); 
     return delegate.call(ctx); 
    } 
} 

RangeWrapper只存儲從和請求。

public class RangeWrapper { 

    private int from; 
    private int to; 

    public RangeWrapper(String range, int totalLength) { 
     // check range header for content 
     if (range != null) { 
      String[] intermediary = range.split("=")[1].split("-"); 
      this.from = Integer.parseInt(intermediary[0]); 

      if (intermediary.length > 1) { 
       this.to = Integer.parseInt(intermediary[1]); 
      } else { 
       this.to = totalLength - 1; 
      } 
     } else { 

      this.from = 0; 
      this.to = totalLength - 1; 
     } 
    } 


    /** Getters */ 
    public int getFrom() { 
     return this.from; 
    } 

    public int getTo() { 
     return this.to; 
    } 

    public int getContentLength() { 
     return this.to - this.from + 1; 
    } 
} 

現在的實際問題。 Play Server可以處理的實例數量似乎非常有限,我認爲這與ByteChunks的同步性質有關。在下面的圖片中,您可以看到只有五個請求正在滿足數據。其餘的似乎沒有得到任何內容。有人有解決這個問題的辦法嗎?

Only five simultanious streams can be handled.

問候,蒂姆

回答

1

getContentLength方法是不正確的,因爲它返回負長度:

MP3 size = 12000 
from = 0 
to = 5000 
getContentLength = -4999 

修復此方法,它應該工作。

除此之外,您應該注意,rangechunks是靜態字段,您可能會遇到併發問題。在Play控制器中,默認情況下也是異步的,所以我認爲包裝你的代碼並不是必須的。

+0

感謝您指出getContentLength()錯誤!至於靜態字段,我今天要測試它,並且會回到接受你的答案。 –

相關問題