最近要做一个新项目,里面涉及到图片等文件的上传,具体的流程是通过客户端产生的流把图片传给服务器端,然后服务器端就把此文件存到apache服务器下,接着,把存放的地址再返回给客户端。刚开始的时候直接是把图片存放到Tomcat的webapps下,但是,始终通过URL访问不到,再加上tomcat有的弊端,就是一定得重启才行。所以,讨论之后决定用静态的apache服务器实现算了。下面是具体的编写过程:
1、创建一个web工程fileUpload,然后把相应的jar包引入进去,如下:
2、编写struts的配置文件,struts-config.xml,你可以将其存放到src下,这样的话就不必在web.xml中进行配置啦,我的是直接放到了webcontent下,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <action-mappings> <!-- 多文件上传 --> <action path="/uploadfiles" type="com.zlb.action.UploadAction" validate="false" /> </action-mappings> </struts-config>
3、编辑web.xml配置文件,如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>uploadFile</display-name> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
这时,你发现我对struts的配置文件的路径进行了引入。值得注意的还有一点,就是对action的URL进行定义时一定不能用”/*“,你可以用”*.do“或者”*.action“等,要不然的话你在执行上传的时候会报错,网上有好多关于这种情况的解答,想了解的朋友可以自己去看看
3、接下来就是比较重要的action的编写啦~~~~
在这里我就不把详细的代码贴出来了,就一步步的讲解一下吧:
// 创建磁盘工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存缓冲大小
factory.setSizeThreshold(Integer.parseInt(memorySize));
// 创建处理工具
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大允许的尺寸
int setFileSize = Integer.parseInt(sizeMax);
upload.setSizeMax(setFileSize);
// 设置临时目录
File file = new File(tempDir);
//因怕此目录可能不存在,所以先进行下判断
if(!file.exists()){
file.mkdir();
}
//先对request做下判断,如果无效,则直接返回 String contentType = request.getContentType(); if(contentType == null && "".equals(contentType)){ out.print("File Upload Error"); return; }
// 解析List<FileItem> fileItems = upload.parseRequest(request);Iterator<FileItem> iter = fileItems.iterator();for (; iter.hasNext();) {FileItem fileItem = (FileItem) iter.next();// 判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回falseif
(fileItem.isFormField()) {// 当前是一个表单项out.print("form field : "+ fileItem.getFieldName() + ", "+ fileItem.getString());} else {// 当前是一个上传的文件String fileName = fileItem.getName();File fileDir = new File(photoDir + fileName);fileItem.write(fileDir);out.print(photoUrl
+ fileName);}} 里面的各种参数都要自己进行设置,他们所代表的含义为:
private String tempDir="";//存储图片的临时目录 private String photoDir="";//照片目录 private String photoUrl="";//照片的URL private String memorySize="";//内存缓冲大小 private String sizeMax="";//文件允许的最大值至此,所有的代码都已完成。但是,如果出现并发情况下我们该怎么办呢?很多人都会想到使用多线程处理,我们这里就也加个线程池对其进行处理,代码编写如下:
ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
然后直接通过threadPool .execute()执行即可。此线程池表示有多少个任务就创建多少个线程,若是存在未使用的,则会重用之前的线程,若是线程的空闲时间到了60S,则它会自动对其进行回收,应该说这是创建线程池的首选吧!
好了,介绍就到这里,接下来问题就随之而来了。当把文件上传的代码放到此线程池中对其执行时,就会出现问题:
”List<FileItem> fileItems = upload.parseRequest(request);“这一句怎么也通不过,要么就是报异常,具体问题请点击查看。
若有知道答案的还望告诉我一声,谢谢啦!
更多有关文件上传与下载的文章请点击!