Search in sources :

Example 11 with ChunkedFile

use of io.netty.handler.stream.ChunkedFile in project async-http-client by AsyncHttpClient.

the class HttpStaticFileServerHandler method channelRead0.

@Override
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
    if (!request.decoderResult().isSuccess()) {
        sendError(ctx, BAD_REQUEST);
        return;
    }
    if (request.method() != GET) {
        sendError(ctx, METHOD_NOT_ALLOWED);
        return;
    }
    final String uri = request.uri();
    final String path = sanitizeUri(uri);
    if (path == null) {
        sendError(ctx, FORBIDDEN);
        return;
    }
    File file = new File(path);
    if (file.isHidden() || !file.exists()) {
        sendError(ctx, NOT_FOUND);
        return;
    }
    if (file.isDirectory()) {
        if (uri.endsWith("/")) {
            sendListing(ctx, file);
        } else {
            sendRedirect(ctx, uri + '/');
        }
        return;
    }
    if (!file.isFile()) {
        sendError(ctx, FORBIDDEN);
        return;
    }
    // Cache Validation
    String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE);
    if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
        SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
        Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
        // Only compare up to the second because the datetime format we send to the client
        // does not have milliseconds
        long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
        long fileLastModifiedSeconds = file.lastModified() / 1000;
        if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
            sendNotModified(ctx);
            return;
        }
    }
    RandomAccessFile raf;
    try {
        raf = new RandomAccessFile(file, "r");
    } catch (FileNotFoundException ignore) {
        sendError(ctx, NOT_FOUND);
        return;
    }
    long fileLength = raf.length();
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    HttpUtil.setContentLength(response, fileLength);
    setContentTypeHeader(response, file);
    setDateAndCacheHeaders(response, file);
    if (HttpUtil.isKeepAlive(request)) {
        response.headers().set(CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }
    // Write the initial line and the header.
    ctx.write(response);
    // Write the content.
    ChannelFuture sendFileFuture;
    ChannelFuture lastContentFuture;
    if (ctx.pipeline().get(SslHandler.class) == null) {
        sendFileFuture = ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
        // Write the end marker.
        lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
    } else {
        sendFileFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)), ctx.newProgressivePromise());
        // HttpChunkedInput will write the end marker (LastHttpContent) for us.
        lastContentFuture = sendFileFuture;
    }
    sendFileFuture.addListener(new ChannelProgressiveFutureListener() {

        @Override
        public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
            if (total < 0) {
                // total unknown
                System.err.println(future.channel() + " Transfer progress: " + progress);
            } else {
                System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);
            }
        }

        @Override
        public void operationComplete(ChannelProgressiveFuture future) {
            System.err.println(future.channel() + " Transfer complete.");
        }
    });
    // Decide whether to close the connection or not.
    if (!HttpUtil.isKeepAlive(request)) {
        // Close the connection when the whole content is written out.
        lastContentFuture.addListener(ChannelFutureListener.CLOSE);
    }
}
Also used : ChunkedFile(io.netty.handler.stream.ChunkedFile) FileNotFoundException(java.io.FileNotFoundException) SslHandler(io.netty.handler.ssl.SslHandler) RandomAccessFile(java.io.RandomAccessFile) RandomAccessFile(java.io.RandomAccessFile) ChunkedFile(io.netty.handler.stream.ChunkedFile) File(java.io.File) SimpleDateFormat(java.text.SimpleDateFormat)

Aggregations

RandomAccessFile (java.io.RandomAccessFile)9 ChunkedFile (io.netty.handler.stream.ChunkedFile)8 File (java.io.File)8 FileNotFoundException (java.io.FileNotFoundException)8 ChannelFuture (io.netty.channel.ChannelFuture)6 DefaultFileRegion (io.netty.channel.DefaultFileRegion)6 SimpleDateFormat (java.text.SimpleDateFormat)6 SslHandler (io.netty.handler.ssl.SslHandler)5 IOException (java.io.IOException)5 Date (java.util.Date)5 HttpChunkedInput (io.netty.handler.codec.http.HttpChunkedInput)4 ChannelProgressiveFuture (io.netty.channel.ChannelProgressiveFuture)3 ChannelProgressiveFutureListener (io.netty.channel.ChannelProgressiveFutureListener)3 DefaultHttpResponse (io.netty.handler.codec.http.DefaultHttpResponse)3 HttpResponse (io.netty.handler.codec.http.HttpResponse)3 InputStream (java.io.InputStream)3 URI (java.net.URI)3 URL (java.net.URL)3 ChannelFuture (org.apache.flink.shaded.netty4.io.netty.channel.ChannelFuture)3 DefaultFileRegion (org.apache.flink.shaded.netty4.io.netty.channel.DefaultFileRegion)3