我想检查上传文件的大小,并防止完全载入到内存中的文件.我使用CommonsMultipartFile.上传的文件将被处理并保存在数据库中. AbstractCoupleUploadController类处理包含文件的传入请求:
public abstract class AbstractCoupleUploadController extends RemoteServiceServlet implements ServletContextAware,UploadServlet
{
...
@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:
我的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 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 factory)
{
this(null,factory);
}
public CoupleUploadPanel(String url,UploadServletAsync factory)
{
this.factory = (SerializationStreamFactory) factory;
if(url != null)
{
setAction(url);
}
init();
}
public CoupleUploadPanel(String target,String url,UploadServletAsync 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
{
void upload(T model,AsyncCallback callback);
}
public interface UploadServlet extends RemoteService
{
void upload(T model);
}
所以uploadPanel将以这种方式被实例化:
uploadPanel= new CoupleUploadPanel((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
{
String URL = "**/uploadFileService.mvc";
}
public interface UploadFileServletAsync extends UploadServletAsync
{
public static final UploadFileServletAsync INSTANCE = GWT.create(UploadFileServlet.class);
}
在服务器端:UploadFileServletImpl扩展AbstractCoupleUploadController并实现upload()方法(上传过程):
@RequestMapping(UploadFileServlet.URL)
public class UploadFileServletImpl extends AbstractCoupleUploadController
{
...
@Override
protected UploadResultModel upload(WorkshopHistoryModel model,MultipartFile firstFile,MultipartFile secondFile)
throws ProcessRequestException
{
return workshopHistoryService.submitList(model.getWorkshop(),secondFile);
}
...
}