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();
}
}
}
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);
}
}
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);
}
}
Aggregations