1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.embedded;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.RandomAccessFile;
24 import java.nio.ByteBuffer;
25 import java.nio.channels.FileChannel;
26 import java.nio.channels.FileChannel.MapMode;
27 import java.nio.file.StandardOpenOption;
28
29 import javax.servlet.AsyncContext;
30 import javax.servlet.ServletException;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.eclipse.jetty.http.MimeTypes;
35 import org.eclipse.jetty.server.Handler;
36 import org.eclipse.jetty.server.HttpOutput;
37 import org.eclipse.jetty.server.Request;
38 import org.eclipse.jetty.server.Server;
39 import org.eclipse.jetty.server.handler.AbstractHandler;
40 import org.eclipse.jetty.server.handler.DefaultHandler;
41 import org.eclipse.jetty.server.handler.HandlerList;
42 import org.eclipse.jetty.server.handler.ResourceHandler;
43 import org.eclipse.jetty.servlet.DefaultServlet;
44 import org.eclipse.jetty.util.Callback;
45 import org.eclipse.jetty.util.URIUtil;
46 import org.eclipse.jetty.util.resource.Resource;
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class FastFileServer
61 {
62 public static void main( String[] args ) throws Exception
63 {
64 Server server = new Server(8080);
65
66 HandlerList handlers = new HandlerList();
67 handlers.setHandlers(new Handler[] {
68 new FastFileHandler(new File(System.getProperty("user.dir"))),
69 new DefaultHandler() });
70 server.setHandler(handlers);
71
72 server.start();
73 server.join();
74 }
75
76 static class FastFileHandler extends AbstractHandler
77 {
78 private final MimeTypes mimeTypes = new MimeTypes();
79 private final File dir;
80
81 private FastFileHandler( File dir )
82 {
83 this.dir = dir;
84 }
85
86 @Override
87 public void handle( String target,
88 Request baseRequest,
89 HttpServletRequest request,
90 HttpServletResponse response ) throws IOException,
91 ServletException
92 {
93
94
95
96 final int SMALL = response.getBufferSize();
97 final int MEDIUM = 8 * SMALL;
98
99
100 final File file = new File(this.dir, request.getPathInfo());
101
102
103 if (!file.exists())
104 return;
105
106
107 baseRequest.setHandled(true);
108
109
110 if (file.isDirectory())
111 {
112 if (!request.getPathInfo().endsWith(URIUtil.SLASH))
113 {
114 response.sendRedirect(response.encodeRedirectURL(URIUtil
115 .addPaths(request.getRequestURI(), URIUtil.SLASH)));
116 return;
117 }
118 String listing = Resource.newResource(file).getListHTML(
119 request.getRequestURI(),
120 request.getPathInfo().lastIndexOf("/") > 0);
121 response.setContentType("text/html; charset=utf-8");
122 response.getWriter().println(listing);
123 return;
124 }
125
126
127
128
129
130 response.setDateHeader("Last-Modified", file.lastModified());
131 response.setDateHeader("Content-Length", file.length());
132 response.setContentType(mimeTypes.getMimeByExtension(file.getName()));
133
134
135 if (file.length() < SMALL)
136 {
137
138 ((HttpOutput) response.getOutputStream())
139 .sendContent(FileChannel.open(file.toPath(),
140 StandardOpenOption.READ));
141 return;
142 }
143
144
145
146 final AsyncContext async = request.startAsync();
147 Callback completionCB = new Callback()
148 {
149 @Override
150 public void succeeded()
151 {
152
153 async.complete();
154 }
155
156 @Override
157 public void failed( Throwable x )
158 {
159
160 x.printStackTrace();
161 async.complete();
162 }
163 };
164
165
166 if (file.length() < MEDIUM)
167 {
168
169 ((HttpOutput) response.getOutputStream())
170 .sendContent(FileChannel.open(file.toPath(),
171 StandardOpenOption.READ), completionCB);
172 return;
173 }
174
175
176
177
178
179 ByteBuffer buffer;
180 try ( RandomAccessFile raf = new RandomAccessFile(file, "r"); )
181 {
182 buffer = raf.getChannel().map(MapMode.READ_ONLY, 0,
183 raf.length());
184 }
185
186
187
188 buffer = buffer.asReadOnlyBuffer();
189
190
191
192 ((HttpOutput) response.getOutputStream()).sendContent(buffer,
193 completionCB);
194 }
195 }
196 }