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();