- public abstract class AbstractCoupleUploadController<T extends Serializable> extends RemoteServiceServlet implements ServletContextAware,UploadServlet<WorkshopHistoryModel>
- {
- ...
- @RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
- public ModelAndView handleRequest(@RequestParam("firstFile") CommonsMultipartFile firstFile,@RequestParam("secondFile") CommonsMultipartFile secondFile,HttpServletRequest request,HttpServletResponse response)
- {
- synchronized(this)
- {
- initThreads();
- perThreadRequest.set(request);
- perThreadResponse.set(response);
- }
- handleUpload(firstFile,secondFile,request,response);
- response.getWriter().flush();
- response.flushBuffer();
- return null;
- }
- private void handleUpload(CommonsMultipartFile firstFile,CommonsMultipartFile secondFile,HttpServletResponse response) throws IOException
- {
- response.setContentType("text/html");
- if(firstFile.getSize() == 0 || secondFile.getSize() == 0)
- {
- response.getWriter().print(AppConstants.UPLOAD_ZERO_SIZE_FILE);
- return;
- }
- // other validations
- // uploading:
- try
- {
- String content = request.getParameter(CoupleUploadPanel.CONTENT);
- T model = deserialize(content);
- UploadResultModel resultModel = upload(model,firstFile,secondFile); // it's implemented in UploadFileServletImpl
- if(resultModel.hasCriticalError())
- {
- response.getWriter().print(AppConstants.UPLOAD_FAIL + "," + String.valueOf(resultModel.getWorkshopHistoryId()));
- }
- else
- {
- response.getWriter().print(AppConstants.UPLOAD_SUCCESS + "," + String.valueOf(resultModel.getWorkshopHistoryId()));
- }
- }
- catch(ProcessRequestException e)
- {
- // write upload error description in response.getWriter()
- }
- catch(Exception e)
- {
- e.printStackTrace();
- response.getWriter().print(AppConstants.UPLOAD_UNKOWN_ERROR);
- }
- }
- ...
- }
我的app-servlet.xml(file.upload.max_size = 9437184)中有一个multipartResolver bean,另外还有一个用于处理UploadSizeExceededExceptions的maxUploadSizeExceptionExceptionHandler bean:
- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
- <property name="maxUploadSize" value="${file.upload.max_size}" />
- </bean>
- <bean id="maxUploadSizeExceededExceptionHandler" class="com.insurance.ui.server.uploadfile.MaxUploadSizeExceededExceptionHandler">
- <property name="order" value="1"/>
- </bean>
我的maxUploadSizeExceededExceptionHandler:
- public class MaxUploadSizeExceededExceptionHandler implements HandlerExceptionResolver,Ordered
- {
- private int order;
- @Override
- public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)
- {
- if(ex instanceof MaxUploadSizeExceededException)
- {
- try
- {
- response.getWriter().print(ErrorConstants.UPLOAD_SIZE_EXCEED + "," + (((MaxUploadSizeExceededException) ex).getMaxUploadSize()/(1024*1024)));
- response.getWriter().flush();
- response.flushBuffer();
- return new ModelAndView();
- }
- catch(IOException e)
- {
- }
- }
- return null;
- }
- ...
- }
当我上传一个非常大的文件(超过${file.upload.max_size},大约700MB),CommonsMultipartResolver立即抛出MaxUploadSizeExceededException,它正在捕获和处理它(在response.getWriter()中写)).我的问题:我的浏览器上传进度条显示文件仍在上传!为什么?
更新:我正在使用:
> Spring – * – 3.0.5.RELEASE
> commons-fileupload-1.1.1
并尝试:
> Spring – * – 3.1.2.RELEASE
> commons-fileupload-1.3
和我的AS:
> Tomcat 6(开发中)
> Jboss 7(生产中)
更新2:在客户端,我使用GWT(我认为没关系):
点击submitRequestButton开始上传:
- @UiHandler("submitRequestButton")
- public void submitRequestButtonClick(ClickEvent event)
- {
- try
- {
- // some validation
- submitRequestButton.setEnabled(false);
- uploadPanel.upload(model.getWorkshopHistoryModel()); // uploadPanel is from the CoupleUploadPanel type
- }
- catch(ValidationException exception)
- {
- // handle validation errors
- }
- catch(SerializationException e)
- {
- // handle serialization errors
- }
- }
我有一个CoupleUploadPanel小部件上传(两个文件):
- public class CoupleUploadPanel<T extends Serializable> extends FormPanel
- {
- public final static String CONTENT = "content";
- private static final String FIRST_FILE = "firstFile";
- private static final String SECOND_FILE = "secondFile";
- private Hidden contentInput;
- private FileUpload firstFileUploadInput;
- private FileUpload secondFileUploadInput;
- private SerializationStreamFactory factory;
- public CoupleUploadPanel(UploadServletAsync<T> factory)
- {
- this(null,factory);
- }
- public CoupleUploadPanel(String url,UploadServletAsync<T> factory)
- {
- this.factory = (SerializationStreamFactory) factory;
- if(url != null)
- {
- setAction(url);
- }
- init();
- }
- public CoupleUploadPanel(String target,String url,UploadServletAsync<T> factory)
- {
- super(target);
- this.factory = (SerializationStreamFactory) factory;
- if(url != null)
- {
- setAction(url);
- }
- init();
- }
- private void init()
- {
- setMethod("POST");
- setEncoding(ENCODING_MULTIPART);
- firstFileUploadInput = new FileUpload();
- firstFileUploadInput.setName(CoupleUploadPanel.FIRST_FILE);
- secondFileUploadInput = new FileUpload();
- secondFileUploadInput.setName(CoupleUploadPanel.SECOND_FILE);
- contentInput = new Hidden();
- contentInput.setName(CONTENT);
- VerticalPanel panel = new VerticalPanel();
- panel.add(firstFileUploadInput);
- panel.add(secondFileUploadInput);
- panel.add(contentInput);
- add(panel);
- }
- public void upload(T input) throws SerializationException
- {
- contentInput.setValue(serialize(input));
- submit();
- }
- private String serialize(T input) throws SerializationException
- {
- SerializationStreamWriter writer = factory.createStreamWriter();
- writer.writeObject(input);
- return writer.toString();
- }
- }
我们应该将UploadServletAsync传递给CoupleUploadPanel构造函数. UploadServletAsync和UploadServlet接口:
- public interface UploadServletAsync<T extends Serializable>
- {
- void upload(T model,AsyncCallback<Void> callback);
- }
- public interface UploadServlet<T extends Serializable> extends RemoteService
- {
- void upload(T model);
- }
所以uploadPanel将以这种方式被实例化:
- uploadPanel= new CoupleUploadPanel<WorkshopHistoryModel>((UploadFileServletAsync) GWT.create(UploadFileServlet.class));
- uploadPanel.setAction(UploadFileServlet.URL);
并且添加到uploadPanel(onSumbitComplete()的SubmitCompeleteHandler将在提交完成时被调用,结果传递给客户端):
- uploadPanel.addSubmitCompleteHandler(new SubmitCompleteHandler()
- {
- @Override
- public void onSubmitComplete(SubmitCompleteEvent event)
- {
- String s = event.getResults(); //contains whatever written by response.getWriter()
- if(s == null)
- {
- // navigate to request list page
- }
- else
- {
- String[] response = s.split(",");
- // based on response:
- // show error messages if any error occurred in file upload
- // else: navigate to upload result page
- }
- }
- });
UploadFileServlet和UploadFileServletAsync接口:
- public interface UploadFileServlet extends UploadServlet<WorkshopHistoryModel>
- {
- String URL = "**/uploadFileService.mvc";
- }
- public interface UploadFileServletAsync extends UploadServletAsync<WorkshopHistoryModel>
- {
- public static final UploadFileServletAsync INSTANCE = GWT.create(UploadFileServlet.class);
- }
在服务器端:UploadFileServletImpl扩展AbstractCoupleUploadController并实现upload()方法(上传过程):
- @RequestMapping(UploadFileServlet.URL)
- public class UploadFileServletImpl extends AbstractCoupleUploadController<WorkshopHistoryModel>
- {
- ...
- @Override
- protected UploadResultModel upload(WorkshopHistoryModel model,MultipartFile firstFile,MultipartFile secondFile)
- throws ProcessRequestException
- {
- return workshopHistoryService.submitList(model.getWorkshop(),secondFile);
- }
- ...
- }
解决方法
在我最后一次安装过程中,我曾经用过Nginx作为Tomcat前面的代理:
>如果您的浏览器发送实际的文件大小(现代浏览器,至少IE7?或IE8?),Nginx将发送500,如果大小超过定义的限制.>我不是100%肯定:如果上传的大小超过指定的限制,Nginx也会发送一个500.这也将取消与Tomcat的底层连接.