forked from laomafeima/WebJava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStaticFileServer.java
More file actions
194 lines (174 loc) · 6.8 KB
/
StaticFileServer.java
File metadata and controls
194 lines (174 loc) · 6.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package Web;
import java.nio.channels.SocketChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.TimeUnit;
/**
* 静态文件服务器
*
* @author Ma
*/
public class StaticFileServer {
public Request request;
public int size;
public ByteBuffer byteBuffer;
public SocketChannel socketChannel;
public Path filePath;
public String ExName;//扩展名字
/**
* 初始化一些东西
*
* @param request
*/
public StaticFileServer(Request request) {
this.request = request;
String path = Options.StaticPath + this.request.Path.substring(8);
this.filePath = Paths.get(path);
//设置扩展名
int index = this.request.Path.lastIndexOf(".");
this.ExName = this.request.Path.substring(index + 1);
}
/**
* 检测文件是否存在
*
* @return
*/
public boolean exists() {
return Files.exists(filePath);
}
/**
* 检查文件是否需要更新还是304状态吗
*
* @return
*/
public boolean update() {
try {
int lastTime = (int) Files.getLastModifiedTime(filePath).to(TimeUnit.SECONDS);//获取最后修改的时间戳
Object paramTime = this.request.Header.get("If-Modified-Since");
if ((paramTime != null) && (Integer.parseInt((String) paramTime) <= lastTime)) {
//处理304
Response.setStatus(304);
Response.setContentType(Response.findContentType(this.ExName));
Response.header("Last-Modified: " + lastTime);
Response.header("Cache-Control:public, max-age=2592000");
byte[] headerBytes = Response.getHeader().getBytes();
ByteBuffer writerBuffer = ByteBuffer.allocate(headerBytes.length);
writerBuffer.clear();
writerBuffer.put(headerBytes);
writerBuffer.flip();
while (writerBuffer.hasRemaining()) {
this.socketChannel.write(writerBuffer);
}
writerBuffer.clear();
this.socketChannel.close();
//输出debug信息
if (Options.DEBUG || Options.ParseLine) {
System.out.println(Response.Status + " " + this.request.Header.get("Host") + this.request.Path);
}
Response.finish();//清理信息
return false;
}
} catch (IOException ex) {
Logger.getLogger(StaticFileServer.class.getName()).log(Level.SEVERE, null, ex);
}
return true;
}
public void read(SocketChannel socketChannel) {
this.socketChannel = socketChannel;
//处理304
if (this.update()) {
//输出debug信息
if (Options.DEBUG || Options.ParseLine) {
System.out.println("Static File" + " " + this.request.Header.get("Host") + this.request.Path);
}
//处理200
BasicFileAttributeView basicView = Files.getFileAttributeView(this.filePath, BasicFileAttributeView.class);
try {
BasicFileAttributes basicAttrs = basicView.readAttributes();
long size = basicAttrs.size();
if (size > 2097152) {
//说明文件大于2M
}
this.size = (int) size;
int lastTime = (int) Files.getLastModifiedTime(filePath).to(TimeUnit.SECONDS);//获取最后修改的时间戳
this.byteBuffer = ByteBuffer.allocate((int) size);//申请缓存空间
//开始获取通道,读取文件
AsynchronousFileChannel afc = AsynchronousFileChannel.open(this.filePath);
afc.read(byteBuffer, 0, lastTime, new CompletionHandlerImpl(afc));
} catch (IOException ex) {
//处理500错误
Logger.getLogger(StaticFileServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* 成员类 处理文件完成后的操作
*/
private class CompletionHandlerImpl implements CompletionHandler<Integer, Object> {
AsynchronousFileChannel afc;
public CompletionHandlerImpl(AsynchronousFileChannel afc) {
this.afc = afc;
}
/**
* 处理成功的操作
*
* @param result
* @param attachment
*/
@Override
public void completed(Integer result, Object attachment) {
Integer lastModifyInteger = (Integer) attachment;
int lastModify = lastModifyInteger.intValue();
//Header不能使用Response
String header = "HTTP/1.1 200 OK\r\n"
+ "Content-type: " + Response.findContentType(StaticFileServer.this.ExName) + ";\r\n"
+ "Content-ength: " + StaticFileServer.this.size + "\r\n"
+ "Last-Modified: " + lastModify + "\r\n"
+ "Cache-Control:public, max-age=2592000 \r\n"
+ "Server: " + Response.Server + "\r\n\r\n";
byte[] headerBytes = header.getBytes();
byte[] contentBytes = StaticFileServer.this.byteBuffer.array();
ByteBuffer writerBuffer = ByteBuffer.allocate(headerBytes.length + contentBytes.length);
writerBuffer.clear();
writerBuffer.put(headerBytes);
writerBuffer.put(contentBytes);
writerBuffer.flip();
try {
while (writerBuffer.hasRemaining()) {
StaticFileServer.this.socketChannel.write(writerBuffer);
}
writerBuffer.clear();
StaticFileServer.this.socketChannel.close();
this.afc.close();
} catch (IOException ex) {
Logger.getLogger(StaticFileServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* 处理失败的操作
*
* @param exc
* @param attachment
*/
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println(exc.getCause());
//@todo 处理500错误
try {
StaticFileServer.this.socketChannel.close();
this.afc.close();
} catch (IOException ex) {
Logger.getLogger(StaticFileServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}