package com.ekexiu.portal.service; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.LinkedList; import java.util.List; import org.jfw.apt.web.annotation.Path; import org.jfw.apt.web.annotation.operate.Post; import org.jfw.apt.web.annotation.param.Upload; import org.jfw.util.StringUtil; import org.jfw.util.exception.JfwBaseException; import org.jfw.util.web.fileupload.Item; import org.jfw.util.web.fileupload.UploadItemIterator; @Path("/file") public class FileUploadService { private long millisecondInOnDay = 1000 * 60 * 60 * 24; private long fileMaxSize = 10 * 1024 * 1024; private long fileMaxCount = Long.MAX_VALUE; private String fileExtList = null; private File rootPath; public long getFileMaxSize() { return fileMaxSize; } public void setFileMaxSize(long fileMaxSize) { this.fileMaxSize = fileMaxSize; } public long getFileMaxCount() { return fileMaxCount; } public void setFileMaxCount(long fileMaxCount) { this.fileMaxCount = fileMaxCount; } public String getFileExtList() { return fileExtList; } public void setFileExtList(String fileExtList) { if (fileExtList.trim().length() == 0) this.fileExtList = null; else this.fileExtList = fileExtList; } public File getRootPath() { return rootPath; } public void setRootPath(File rootPath) { this.rootPath = rootPath; } private void remove(List files) { for (UploadFile f : files) f.getFn().delete(); } private boolean validFileExt(String ext) { if (this.fileExtList == null) return true; if (ext.length() == 0) return false; return this.fileExtList.indexOf("," + ext + ",") >= 0; } private String normalizeFileName(String fn) { int index = fn.indexOf('\\'); if (index >= 0) { fn = fn.substring(fn.lastIndexOf('\\') + 1); } index = fn.indexOf('/'); if (index >= 0) { fn = fn.substring(fn.lastIndexOf('/') + 1); } if (fn.length() == 0) throw new RuntimeException("invalid filename in Multipart/data request"); return fn; } private UploadFile buildTargetFile(String ext) { File path = new File(this.rootPath, String.valueOf(System.currentTimeMillis() / millisecondInOnDay)); if (!path.exists()) path.mkdirs(); File file; do { String fn = StringUtil.buildUUID(); if (ext.isEmpty()) { file = new File(path, fn); } else { file = new File(path, fn + "." + ext); } } while (file.exists()); UploadFile uf = new UploadFile(); uf.setFn(file); return uf; } @Post @Path("/upload") public List upload(@Upload UploadItemIterator it) throws Exception { List ret = new LinkedList(); try { long fileCount = 0; while (it.hasNext()) { Item item = it.next(); if (!item.isFormField()) { ++fileCount; if (fileCount > this.fileMaxCount) throw new JfwBaseException(-1, "invalid file count"); String name = normalizeFileName(item.getName()); int index = name.lastIndexOf('.'); String ext = index >= 0 ? name.substring(index + 1) : ""; ext = ext.trim(); if (!this.validFileExt(ext)) throw new JfwBaseException(-2, "invalid file ext"); long fileLen = 0; int len = 0; UploadFile uf = this.buildTargetFile(ext); uf.setName(name); File file = uf.getFn(); uf.setUri(file.getParentFile().getName() + "/" + file.getName()); ret.add(uf); byte[] buf = new byte[8092]; OutputStream of = new FileOutputStream(file); try { InputStream in = item.getInputStream(); try { while ((len = in.read(buf)) >= 0) { if (len > 0) { of.write(buf, 0, len); fileLen += len; if (fileLen > this.fileMaxCount) throw new JfwBaseException(-3, "invalid file size"); } } uf.setSize(fileLen); } finally { in.close(); } } finally { of.close(); } } } return ret; } catch (Exception e) { this.remove(ret); throw e; } finally { if (it != null) it.clean(); } } public static class UploadFile { private String name; private String uri; private long size; private transient File fn; public File getFn() { return fn; } public void setFn(File fn) { this.fn = fn; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } } }