Search in sources :

Example 1 with DefaultFileRegion

use of org.jboss.netty.channel.DefaultFileRegion in project feeyo-hlsserver by variflight.

the class ResourceFileDownloadGetHandler method execute.

public void execute(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
    HttpRequest request = (DefaultHttpRequest) e.getMessage();
    String uri = request.getUri();
    final String path = HlsCtx.INSTANCE().getHomePath() + File.separator + "resources";
    String fileName = path + uri;
    RandomAccessFile raf;
    try {
        File file = new File(fileName);
        if (file.isHidden() || !file.exists() || !file.isFile()) {
            HttpUtil.sendError(ctx, HttpResponseStatus.NOT_FOUND);
            return;
        }
        String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE);
        if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
            SimpleDateFormat dateFormatter = new SimpleDateFormat(HttpUtil.HTTP_DATE_FORMAT, Locale.US);
            Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
            long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
            long fileLastModifiedSeconds = file.lastModified() / 1000;
            if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
                HttpUtil.sendNotModified(ctx);
                return;
            }
        }
        raf = new RandomAccessFile(file, READ_ONLY);
        long fileLength = raf.length();
        long timeMillis = System.currentTimeMillis();
        long expireMillis = timeMillis + HTTP_CACHE_SECONDS * 1000;
        final DefaultHttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
        response.headers().add(HttpHeaders.Names.CONTENT_LENGTH, fileLength);
        response.headers().add(HttpHeaders.Names.CONTENT_TYPE, HttpUtil.getMimeType(request.getUri()) + "; charset=UTF-8");
        response.headers().add(HttpHeaders.Names.DATE, HttpUtil.getCurrentDate());
        // http 1.0的 Expires & Pragma
        response.headers().add(HttpHeaders.Names.EXPIRES, HttpUtil.getDateString(expireMillis));
        /**
         * Expires: Mon, 19 Nov 2012 08:40:01 GMT , 指定cache的绝对过期时间,和Cache-Control一起使用时以后者为准。
         */
        // http 1.1的 Cache-Control
        response.headers().add(HttpHeaders.Names.CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
        /**
         * private : 只有用户端会cache,  public : 用户浏览器和中间proxy都会cache, max-age=xxx : 设置cache的最大存活时间,单位s
         */
        response.headers().add(HttpHeaders.Names.LAST_MODIFIED, HttpUtil.getDateString(file.lastModified()));
        /**
         * 基于最后修改时间的 Last-Modified
         */
        Channel ch = e.getChannel();
        // 写HTTP 初始头部信息
        ch.write(response);
        // 写内容
        ChannelFuture writeFuture;
        if (ch.getPipeline().get(SslHandler.class) != null) {
            // HTTPS 下不能使用零拷贝
            writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
        } else {
            // 没有SSL/TLS、COMPRESS 的情况下, 才可使用零拷贝
            final DefaultFileRegion region = new DefaultFileRegion(raf.getChannel(), 0, fileLength);
            writeFuture = ch.write(region);
            writeFuture.addListener(new ChannelFutureProgressListener() {

                @Override
                public void operationComplete(final ChannelFuture future) {
                    region.releaseExternalResources();
                }

                @Override
                public void operationProgressed(ChannelFuture future, long amount, long current, long total) {
                // LOGGER.info( String.format("%s: %d / %d (+%d)%n", path, current, total, amount) );
                }
            });
        }
    } catch (Exception e2) {
        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
        ChannelFuture channelFuture = ctx.getChannel().write(response);
        if (channelFuture.isSuccess()) {
            channelFuture.getChannel().close();
        }
    }
}
Also used : HttpRequest(org.jboss.netty.handler.codec.http.HttpRequest) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) ChannelFuture(org.jboss.netty.channel.ChannelFuture) Channel(org.jboss.netty.channel.Channel) ChunkedFile(org.jboss.netty.handler.stream.ChunkedFile) DefaultHttpResponse(org.jboss.netty.handler.codec.http.DefaultHttpResponse) HttpResponse(org.jboss.netty.handler.codec.http.HttpResponse) DefaultFileRegion(org.jboss.netty.channel.DefaultFileRegion) Date(java.util.Date) SslHandler(org.jboss.netty.handler.ssl.SslHandler) ChannelFutureProgressListener(org.jboss.netty.channel.ChannelFutureProgressListener) RandomAccessFile(java.io.RandomAccessFile) DefaultHttpRequest(org.jboss.netty.handler.codec.http.DefaultHttpRequest) DefaultHttpResponse(org.jboss.netty.handler.codec.http.DefaultHttpResponse) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) ChunkedFile(org.jboss.netty.handler.stream.ChunkedFile) SimpleDateFormat(java.text.SimpleDateFormat)

Example 2 with DefaultFileRegion

use of org.jboss.netty.channel.DefaultFileRegion in project NabAlive by jcheype.

the class HttpStaticFileServerHandler method messageReceived.

public void messageReceived(ChannelHandlerContext ctx, HttpRequest request) throws Exception {
    // HttpRequest request = (HttpRequest) e.getMessage();
    QueryStringDecoder qs = new QueryStringDecoder(request.getUri());
    if (request.getMethod() != GET) {
        sendError(ctx, METHOD_NOT_ALLOWED);
        return;
    }
    final String path = sanitizeUri(qs.getPath());
    if (path == null) {
        sendError(ctx, FORBIDDEN);
        return;
    }
    boolean toBeCached = false;
    File file = new File(path);
    if (file.isDirectory())
        file = new File(file, "index.html");
    if (!file.exists()) {
        String newPath = path.replaceAll("_[0-9]+(\\.\\w+)$", "$1");
        logger.debug("newPath: {}", newPath);
        file = new File(newPath);
        toBeCached = true;
    }
    logger.debug("search file: {}", file.getAbsolutePath());
    if (file.isHidden() || !file.exists()) {
        sendError(ctx, NOT_FOUND);
        return;
    }
    if (!file.isFile()) {
        sendError(ctx, FORBIDDEN);
        return;
    }
    // Cache Validation
    String ifModifiedSince = request.getHeader(HttpHeaders.Names.IF_MODIFIED_SINCE);
    if (ifModifiedSince != null && !ifModifiedSince.equals("")) {
        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;
    boolean isGz = false;
    try {
        File fileGz = new File(file.getAbsolutePath() + ".gz");
        logger.debug("searching gzip: {}", fileGz.getAbsolutePath());
        String acceptHeader = request.getHeader(Names.ACCEPT_ENCODING);
        if (fileGz.isFile() && acceptHeader != null && acceptHeader.contains("gzip")) {
            isGz = true;
            raf = new RandomAccessFile(fileGz, "r");
        } else
            raf = new RandomAccessFile(file, "r");
    } catch (FileNotFoundException fnfe) {
        sendError(ctx, NOT_FOUND);
        return;
    }
    long fileLength = raf.length();
    HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
    setContentLength(response, fileLength);
    setContentTypeHeader(response, file);
    setDateAndCacheHeaders(response, file, toBeCached);
    if (isGz)
        response.setHeader(Names.CONTENT_ENCODING, "gzip");
    // e.getChannel();
    Channel ch = ctx.getChannel();
    // Write the initial line and the header.
    ch.write(response);
    // Write the content.
    ChannelFuture writeFuture;
    if (ch.getPipeline().get(SslHandler.class) != null) {
        // Cannot use zero-copy with HTTPS.
        writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
    } else {
        // No encryption - use zero-copy.
        final FileRegion region = new DefaultFileRegion(raf.getChannel(), 0, fileLength);
        writeFuture = ch.write(region);
        writeFuture.addListener(new ChannelFutureProgressListener() {

            @Override
            public void operationComplete(ChannelFuture future) {
                region.releaseExternalResources();
            }

            @Override
            public void operationProgressed(ChannelFuture future, long amount, long current, long total) {
                System.out.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
            }
        });
    }
    // Decide whether to close the connection or not.
    if (!isKeepAlive(request)) {
        // Close the connection when the whole content is written out.
        writeFuture.addListener(ChannelFutureListener.CLOSE);
    }
}
Also used : ChannelFuture(org.jboss.netty.channel.ChannelFuture) Channel(org.jboss.netty.channel.Channel) ChunkedFile(org.jboss.netty.handler.stream.ChunkedFile) FileNotFoundException(java.io.FileNotFoundException) DefaultFileRegion(org.jboss.netty.channel.DefaultFileRegion) Date(java.util.Date) SslHandler(org.jboss.netty.handler.ssl.SslHandler) ChannelFutureProgressListener(org.jboss.netty.channel.ChannelFutureProgressListener) RandomAccessFile(java.io.RandomAccessFile) DefaultFileRegion(org.jboss.netty.channel.DefaultFileRegion) FileRegion(org.jboss.netty.channel.FileRegion) RandomAccessFile(java.io.RandomAccessFile) ChunkedFile(org.jboss.netty.handler.stream.ChunkedFile) File(java.io.File) SimpleDateFormat(java.text.SimpleDateFormat)

Example 3 with DefaultFileRegion

use of org.jboss.netty.channel.DefaultFileRegion in project opentsdb by OpenTSDB.

the class HttpQuery method sendFile.

/**
 * Send a file (with zero-copy) to the client.
 * This method doesn't provide any security guarantee.  The caller is
 * responsible for the argument they pass in.
 * @param status The status of the request (e.g. 200 OK or 404 Not Found).
 * @param path The path to the file to send to the client.
 * @param max_age The expiration time of this entity, in seconds.  This is
 * not a timestamp, it's how old the resource is allowed to be in the client
 * cache.  See RFC 2616 section 14.9 for more information.  Use 0 to disable
 * caching.
 */
// Clears warning about RandomAccessFile not
@SuppressWarnings("resource")
public // being closed. It is closed in operationComplete().
void sendFile(final HttpResponseStatus status, final String path, final int max_age) throws IOException {
    if (max_age < 0) {
        throw new IllegalArgumentException("Negative max_age=" + max_age + " for path=" + path);
    }
    if (!channel().isConnected()) {
        done();
        return;
    }
    RandomAccessFile file;
    try {
        file = new RandomAccessFile(path, "r");
    } catch (FileNotFoundException e) {
        logWarn("File not found: " + e.getMessage());
        if (getQueryString() != null && !getQueryString().isEmpty()) {
            // Avoid potential recursion.
            getQueryString().remove("png");
        }
        this.sendReply(HttpResponseStatus.NOT_FOUND, serializer.formatNotFoundV1());
        return;
    }
    final long length = file.length();
    {
        final String mimetype = guessMimeTypeFromUri(path);
        response().headers().set(HttpHeaders.Names.CONTENT_TYPE, mimetype == null ? "text/plain" : mimetype);
        final long mtime = new File(path).lastModified();
        if (mtime > 0) {
            response().headers().set(HttpHeaders.Names.AGE, (System.currentTimeMillis() - mtime) / 1000);
        } else {
            logWarn("Found a file with mtime=" + mtime + ": " + path);
        }
        response().headers().set(HttpHeaders.Names.CACHE_CONTROL, "max-age=" + max_age);
        HttpHeaders.setContentLength(response(), length);
        channel().write(response());
    }
    final DefaultFileRegion region = new DefaultFileRegion(file.getChannel(), 0, length);
    final ChannelFuture future = channel().write(region);
    future.addListener(new ChannelFutureListener() {

        public void operationComplete(final ChannelFuture future) {
            region.releaseExternalResources();
            done();
        }
    });
    if (!HttpHeaders.isKeepAlive(request())) {
        future.addListener(ChannelFutureListener.CLOSE);
    }
}
Also used : ChannelFuture(org.jboss.netty.channel.ChannelFuture) RandomAccessFile(java.io.RandomAccessFile) FileNotFoundException(java.io.FileNotFoundException) DefaultFileRegion(org.jboss.netty.channel.DefaultFileRegion) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) ChannelFutureListener(org.jboss.netty.channel.ChannelFutureListener)

Aggregations

File (java.io.File)3 RandomAccessFile (java.io.RandomAccessFile)3 ChannelFuture (org.jboss.netty.channel.ChannelFuture)3 DefaultFileRegion (org.jboss.netty.channel.DefaultFileRegion)3 FileNotFoundException (java.io.FileNotFoundException)2 SimpleDateFormat (java.text.SimpleDateFormat)2 Date (java.util.Date)2 Channel (org.jboss.netty.channel.Channel)2 ChannelFutureProgressListener (org.jboss.netty.channel.ChannelFutureProgressListener)2 SslHandler (org.jboss.netty.handler.ssl.SslHandler)2 ChunkedFile (org.jboss.netty.handler.stream.ChunkedFile)2 ChannelFutureListener (org.jboss.netty.channel.ChannelFutureListener)1 FileRegion (org.jboss.netty.channel.FileRegion)1 DefaultHttpRequest (org.jboss.netty.handler.codec.http.DefaultHttpRequest)1 DefaultHttpResponse (org.jboss.netty.handler.codec.http.DefaultHttpResponse)1 HttpRequest (org.jboss.netty.handler.codec.http.HttpRequest)1 HttpResponse (org.jboss.netty.handler.codec.http.HttpResponse)1