jfinal现有的文件上传,是用jfinal+cos实现,文件先保存到硬盘后,再获取文件的二进制数据。但这种方式在高频率的文件上传请求的场景,对硬盘的IO要求非常高,影响业务的其它处理。下面是本人修改cos,实现的获取文件流的方法,但不优雅,只是实现了功能。希望jfinal作者能提供该功能,并优雅的实现。
1、在com.oreilly.servlet.MultipartRequest中
public MultipartRequest(HttpServletRequest request, String saveDirectory, int maxPostSize, String encoding, FileRenamePolicy policy) throws IOException {
// Sanity check values
if (request == null)
throw new IllegalArgumentException("request cannot be null");
if (saveDirectory == null)
throw new IllegalArgumentException("saveDirectory cannot be null");
if (maxPostSize <= 0) {
throw new IllegalArgumentException("maxPostSize must be positive");
}
if ("#stream#".equals(saveDirectory)) {
// 把数据流保存为byte[]
saveStream(request, saveDirectory, maxPostSize, encoding);
} else {
// 把数据流保存为File文件
saveFile(request, saveDirectory, maxPostSize, encoding, policy);
}
}
private void saveStream(HttpServletRequest request, String saveDirectory, int maxPostSize, String encoding) throws IOException {
// Parse the incoming multipart, storing files in the dir provided,
// and populate the meta objects which describe what we found
MultipartParser parser = new MultipartParser(request, maxPostSize, true, true, encoding);
// Some people like to fetch query string parameters from
// MultipartRequest, so here we make that possible. Thanks to
// Ben Johnson, ben.johnson@merrillcorp.com, for the idea.
if (request.getQueryString() != null) {
// Let HttpUtils create a name->String[] structure
Hashtable queryParameters = HttpUtils.parseQueryString(request.getQueryString());
// For our own use, name it a name->Vector structure
Enumeration queryParameterNames = queryParameters.keys();
while (queryParameterNames.hasMoreElements()) {
Object paramName = queryParameterNames.nextElement();
String[] values = (String[]) queryParameters.get(paramName);
Vector newValues = new Vector();
for (int i = 0; i < values.length; i++) {
newValues.add(values[i]);
}
parameters.put(paramName, newValues);
}
}
Part part;
while ((part = parser.readNextPart()) != null) {
String name = part.getName();
if (name == null) {
throw new IOException("Malformed input: parameter name missing (known Opera 7 bug)");
}
if (part.isParam()) {
// It's a parameter part, add it to the vector of values
ParamPart paramPart = (ParamPart) part;
String value = paramPart.getStringValue();
Vector existingValues = (Vector) parameters.get(name);
if (existingValues == null) {
existingValues = new Vector();
parameters.put(name, existingValues);
}
existingValues.addElement(value);
} else if (part.isFile()) {
// It's a file part
FilePart filePart = (FilePart) part;
String fileName = filePart.getFileName();
if(fileName == null || fileName.isEmpty()) {
// The field did not contain a file
files.put(name, new UploadedFile(null, null, null, null));
continue;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
// The part actually contained a file
filePart.writeTo(out);
files.put(name, new UploadedFile(saveDirectory, filePart.getFileName(), fileName, filePart.getContentType(), out.toByteArray()));
} catch (Exception e) {
files.put(name, new UploadedFile(null, null, null, null));
e.printStackTrace();
} finally {
out.close();
}
}
}
}2、在UploadedFile中增加private byte[] data;可传递值
3、在com.jfinal.upload.UploadFile中增加private byte[] data;可传递值
4、在com.jfinal.upload.MultipartRequest中
private void wrapMultipartRequest(HttpServletRequest request, String uploadPath, int maxPostSize, String encoding) {
if("#stream#".equals(uploadPath)) {
// 把数据流保存为byte[]
toStream(request, uploadPath, maxPostSize, encoding);
} else {
// 把数据流保存为File文件
toFile(request, uploadPath, maxPostSize, encoding);
}
}
private void toStream(HttpServletRequest request, String uploadPath, int maxPostSize, String encoding) {
uploadFiles = new ArrayList<UploadFile>();
try {
multipartRequest = new com.oreilly.servlet.MultipartRequest(request, uploadPath, maxPostSize, encoding, fileRenamePolicy);
Enumeration files = multipartRequest.getFileNames();
while (files.hasMoreElements()) {
String name = (String)files.nextElement();
String filesystemName = multipartRequest.getFilesystemName(name);
byte[] data = multipartRequest.getByte(name);
// 文件没有上传则不生成 UploadFile, 这与 cos的解决方案不一样
if (filesystemName != null) {
String originalFileName = multipartRequest.getOriginalFileName(name);
String contentType = multipartRequest.getContentType(name);
UploadFile uploadFile = new UploadFile(name, uploadPath, filesystemName, originalFileName, contentType, data);
if (isSafeFile(uploadFile)) {
uploadFiles.add(uploadFile);
}
}
}
// } catch (com.oreilly.servlet.multipart.ExceededSizeException e) {
// throw new ExceededSizeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}5、controller里获取
UploadFile uFile = getFile("file", "#stream#");
uFile.getData();