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 public class FastFileServer
60 {
61 public static void main(String[] args) throws Exception
62 {
63 Server server = new Server(8080);
64
65 HandlerList handlers = new HandlerList();
66 handlers.setHandlers(new Handler[] { new FastFileHandler(new File(".")), new DefaultHandler() });
67 server.setHandler(handlers);
68
69 server.start();
70 server.join();
71 }
72
73 static class FastFileHandler extends AbstractHandler
74 {
75 private final MimeTypes _mimeTypes = new MimeTypes();
76 private final File _dir;
77
78 FastFileHandler(File dir)
79 {
80 _dir=dir;
81 }
82
83 @Override
84 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
85 {
86
87
88 final int SMALL=response.getBufferSize();
89 final int MEDIUM=8*SMALL;
90
91
92
93 final File file = new File(_dir,request.getPathInfo());
94
95
96 if (!file.exists())
97 return;
98
99
100 baseRequest.setHandled(true);
101
102
103 if (file.isDirectory())
104 {
105 if (!request.getPathInfo().endsWith(URIUtil.SLASH))
106 {
107 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH)));
108 return;
109 }
110 String listing = Resource.newResource(file).getListHTML(request.getRequestURI(),request.getPathInfo().lastIndexOf("/") > 0);
111 response.setContentType("text/html; charset=UTF-8");
112 response.getWriter().println(listing);
113 return;
114 }
115
116
117
118 response.setDateHeader("Last-Modified",file.lastModified());
119 response.setDateHeader("Content-Length",file.length());
120 response.setContentType(_mimeTypes.getMimeByExtension(file.getName()));
121
122
123
124
125 if (file.length()<SMALL)
126 {
127
128 ((HttpOutput)response.getOutputStream()).sendContent(FileChannel.open(file.toPath(),StandardOpenOption.READ));
129 return;
130 }
131
132
133
134 final AsyncContext async = request.startAsync();
135 Callback completionCB = new Callback()
136 {
137 @Override
138 public void succeeded()
139 {
140
141 async.complete();
142 }
143
144 @Override
145 public void failed(Throwable x)
146 {
147
148 x.printStackTrace();
149 async.complete();
150 }
151 };
152
153
154
155
156 if (file.length()<MEDIUM)
157 {
158
159 ((HttpOutput)response.getOutputStream()).sendContent(FileChannel.open(file.toPath(),StandardOpenOption.READ),completionCB);
160 return;
161 }
162
163
164
165
166
167 ByteBuffer buffer;
168 try (RandomAccessFile raf = new RandomAccessFile(file,"r");)
169 {
170 buffer=raf.getChannel().map(MapMode.READ_ONLY,0,raf.length());
171 }
172
173
174 buffer=buffer.asReadOnlyBuffer();
175
176
177
178
179 ((HttpOutput)response.getOutputStream()).sendContent(buffer,completionCB);
180 }
181 }
182 }