private ChannelFuture sendFile(ChannelHandlerContext ctx, Channel ch, FileChunk file) throws IOException { RandomAccessFile raf; try { raf = new RandomAccessFile(file.getFile(), "r"); } catch (FileNotFoundException fnfe) { return null; } ChannelFuture writeFuture; if (ch.getPipeline().get(SslHandler.class) != null) { // Cannot use zero-copy with HTTPS. writeFuture = ch.write(new ChunkedFile(raf, file.startOffset(), file.length(), 8192)); } else { // No encryption - use zero-copy. final FileRegion region = new DefaultFileRegion(raf.getChannel(), file.startOffset(), file.length()); writeFuture = ch.write(region); writeFuture.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture future) { region.releaseExternalResources(); } }); } return writeFuture; }
@Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { HttpRequest request = (HttpRequest) e.getMessage(); if (request.getMethod() != GET) { sendError(ctx, METHOD_NOT_ALLOWED); return; } String base = ContainerLocalizer.USERCACHE + "/" + userName + "/" + ContainerLocalizer.APPCACHE + "/" + appId + "/output" + "/"; final Map<String, List<String>> params = new QueryStringDecoder(request.getUri()).getParameters(); List<FileChunk> chunks = Lists.newArrayList(); List<String> taskIds = splitMaps(params.get("ta")); int sid = Integer.valueOf(params.get("sid").get(0)); int partitionId = Integer.valueOf(params.get("p").get(0)); for (String ta : taskIds) { File file = new File(base + "/" + sid + "/" + ta + "/output/" + partitionId); FileChunk chunk = new FileChunk(file, 0, file.length()); chunks.add(chunk); } FileChunk[] file = chunks.toArray(new FileChunk[chunks.size()]); // try { // file = retriever.handle(ctx, request); // } catch (FileNotFoundException fnf) { // LOG.error(fnf); // sendError(ctx, NOT_FOUND); // return; // } catch (IllegalArgumentException iae) { // LOG.error(iae); // sendError(ctx, BAD_REQUEST); // return; // } catch (FileAccessForbiddenException fafe) { // LOG.error(fafe); // sendError(ctx, FORBIDDEN); // return; // } catch (IOException ioe) { // LOG.error(ioe); // sendError(ctx, INTERNAL_SERVER_ERROR); // return; // } // Write the content. Channel ch = e.getChannel(); if (file == null) { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NO_CONTENT); ch.write(response); if (!isKeepAlive(request)) { ch.close(); } } else { HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); long totalSize = 0; for (FileChunk chunk : file) { totalSize += chunk.length(); } setContentLength(response, totalSize); // Write the initial line and the header. ch.write(response); ChannelFuture writeFuture = null; for (FileChunk chunk : file) { writeFuture = sendFile(ctx, ch, chunk); if (writeFuture == null) { sendError(ctx, NOT_FOUND); return; } } // 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); } } }