org.ratpackframework.file.internal.FileHttpTransmitter.java Source code

Java tutorial

Introduction

Here is the source code for org.ratpackframework.file.internal.FileHttpTransmitter.java

Source

/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ratpackframework.file.internal;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.stream.ChunkedFile;

import java.io.*;
import java.util.Date;

public class FileHttpTransmitter {

    public boolean transmit(final File targetFile, HttpResponse response, Channel channel) {
        final RandomAccessFile raf;
        try {
            raf = new RandomAccessFile(targetFile, "r");
        } catch (FileNotFoundException fnfe) {
            throw new RuntimeException(fnfe);
        }

        long fileLength;
        try {
            fileLength = raf.length();
        } catch (IOException e) {
            closeQuietly(raf);
            throw new RuntimeException(e);
        }

        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, fileLength);
        HttpHeaders.setDateHeader(response, HttpHeaders.Names.LAST_MODIFIED, new Date(targetFile.lastModified()));

        // Write the initial line and the header.
        if (!channel.isOpen()) {
            closeQuietly(raf);
            return false;
        }

        try {
            channel.write(response);
        } catch (Exception e) {
            closeQuietly(raf);
        }

        // Write the content.
        ChannelFuture writeFuture;

        ChunkedFile message = null;
        try {
            message = new ChunkedFile(raf, 0, fileLength, 8192);
            writeFuture = channel.write(message);
        } catch (Exception ignore) {
            if (channel.isOpen()) {
                channel.close();
            }
            if (message != null) {
                try {
                    message.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return false;
        }

        final ChunkedFile finalMessage = message;
        writeFuture.addListener(new ChannelFutureListener() {
            public void operationComplete(ChannelFuture future) {
                try {
                    finalMessage.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                future.addListener(ChannelFutureListener.CLOSE);
            }
        });

        return true;
    }

    private void closeQuietly(Closeable closeable) {
        try {
            closeable.close();
        } catch (IOException e1) {
            throw new RuntimeException(e1);
        }
    }

}