我已使用其内置功能在Netty中实现了HTTP-Server。现在我实现了对Range-Headers的支持,它只允许接收页面的一部分。我在netty做的是:
final RandomAccessFile raf = new RandomAccessFile( file, "r" );
raf.seek( ranges[ 0 ] );
HttpResponse response = new DefaultHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.PARTIAL_CONTENT );
// MUST include accept-ranges!!
response.setHeader( HttpHeaders.Names.ACCEPT_RANGES, "bytes" );
// MUST include content-range
response.setHeader( HttpHeaders.Names.CONTENT_RANGE , "bytes " + ranges[ 0 ] + "-" + ranges[ 1 ] + "/" + file.length() );
if ( null != mime )
response.addHeader( HttpHeaders.Names.CONTENT_TYPE, mime.substring( 0, mime.indexOf(' ') ) );
response.setHeader( HttpHeaders.Names.CONTENT_LENGTH, "" + ( ( ranges[ 1 ] - ranges[ 0 ] ) + 1 ) );
event.getChannel().write( response );
event.getChannel().write( new ChunkedInput() {
private boolean endOfStream = false;
private byte[] buffer = new byte[ 4096 ];
private long bytesRead = ranges[ 0 ];
@Override
public boolean hasNextChunk() throws Exception {
return !this.endOfStream;
}
@Override
public Object nextChunk() throws Exception {
if ( false == this.endOfStream ) {
int read = raf.read( this.buffer );
if ( read == -1 || this.bytesRead >= ranges[ 1 ] ) {
this.endOfStream = true;
return new DefaultHttpChunk( ChannelBuffers.EMPTY_BUFFER ); // send isLast
}
if ( this.bytesRead + read > ranges[ 1 ] ) {
read = ( int ) ( ranges[ 1 ] - this.bytesRead ) + 1;
this.bytesRead = ranges[ 1 ]; // next iteration will send last chunk
}
this.bytesRead += read;
return new DefaultHttpChunk( ChannelBuffers.copiedBuffer( this.buffer, 0, read ) );
}
return null;
}
@Override
public boolean isEndOfInput() throws Exception {
return this.endOfStream;
}
@Override
public void close() throws Exception {
raf.close();
}
} ).addListener( ChannelFutureListener.CLOSE );
问题是永远不会调用ChannelFutureListener.CLOSE。我也为侦听器尝试了自己的实现 - 它不会被调用。我认为我的ChunkedInput-Implementation不是问题,我在服务器的不同部分使用相同的原理。当流完成后,它返回ChannelBuffers.EMPTY_BUFFER,然后将从netty调用close,因此流肯定已完成。 我设法解决了在close方法中raf.close之后执行channel.close()的问题,但是这个hack并没有让我开心。我做错了什么?
答案 0 :(得分:0)
一旦isEndOfInput()返回true,FutureListener就会收到通知。所以我认为你应该调试isEndOfInput()在这种情况下是否真的。