解决产品添加页面中有提交文件的解决思路

设计原则

 

在jsp页面的表单里面

<form action="ArticleServlet" enctype="multipart/form-data" method="post">
 <input type="hidden" name="method" value="add"><div>
 
 <input type="text" name="title" id="title" value="" size="60" maxlength="200" /> 

 </div>

后台xxxServlet中

无法通过这种方式进行后台表单数据的接收

String name = request.getparameter(title);

为什么呢?

因为在xxxServlet中 doPost() doGet()方法中没法接收到method方法!!

解决思路见图

formdata类型nginx formdata enctype_表单

使用装饰流设计模式包装httpServletRequest

定义这样一个类

class MultipartrequestWrapper extends HttpRequestWrapper {
  public MultipartRequestWrapper(HttpServletRequest request) {
  super(request);
       
//首先判断是否multipart编码类型
 //如果是multipart编码类型,就逐个从request中取出各个表单域
//contentType:multipart/form-data; boundary=---------------------------317894718690
 //如果表单域是普通的表单域,则将它的值取出,放到allParams中(通过表单上传到服务器是通过requestUtil.copyParam())
 //如果表单域是文件,则
 //1、把文件先存储到磁盘的某个目录中!
 //2、把文件的有关信息(名称,类型,上传时间)包装成Attachment[]类型
 //3、把包装好的Attachment[]类型,放到allParams中
 //拿到迭代器  
try {
 boolean isMultipart = ServletFileUpload.isMultipartContent(request);
 if(!isMultipart){
 allParams = request.getParameterMap();
 }else{

 // Create a new file upload handler
 allParams = new HashMap();
 ServletFileUpload upload = new ServletFileUpload();
 FileItemIterator iter = upload.getItemIterator(request);
 while(iter.hasNext()){
 FileItemStream item = iter.next();//拿到表单域对象
 String name = item.getFieldName();//拿到表单域的名称
 //得到表单域得值(这是一个输入流)
 InputStream stream = item.openStream();
 //如果是普通表单域
 if(item.isFormField()){
 String value = Streams.asString(stream,request.getCharacterEncoding());
 //此处不能直接allParams.put(name,value);如果在表单处有两个相同字段都需要保存下来,如若不保存后面会覆盖前面的
 addFieldsAndValuesToMap(name, value);
 }else{
 //文件附件类型
 if(stream.available()!=0){
 //如果是ie浏览器上传就会把路径也提交上来
 //而我们只需要文件名
 String filename = item.getName();
 if(filename!=null){
 //为了解决IE上传本地文件路径问题
 filename = FilenameUtils.getName(filename);//只需要文件名不需要路径
 }
 //3是否自动关闭
 Streams.copy(stream,new FileOutputStream("D:/temp/update/"+filename), true);
 Attachment attachment = new Attachment();
 attachment.setContentType(item.getContentType());
 attachment.setName(filename);
 attachment.setUploadTime(new Date());
 //如果是多个文件
 addFieldsAndValuesToMap(name, attachment);
 }
 }


 }
 }
 }catch (Exception e) {
 e.printStackTrace();
 }}
 
//为了处理多个上传文件
private void addFieldsAndValuesToMap(String name, Attachment value) {
 Attachment[] fieldValues = (Attachment[]) allParams.get(name);
 if(fieldValues==null){
 allParams.put(name, new Attachment[]{value});
 }else{
 //如果不为空说明map集合里面已经有一份了 
 //'sex','male'界面又传来一个表单仍然需要保存
 //'sex','male',null 
 fieldValues = Arrays.copyOf(fieldValues, fieldValues.length+1);
 //再给新数组赋值
 fieldValues[fieldValues.length-1]=value;//给最后一个赋值最新的value
 allParams.put(name, fieldValues);//
 }

 }/**
 * 目标实现数组的拷贝
 * @param name
 * @param value
 * map的键是唯一的
 */
 private void addFieldsAndValuesToMap(String name, String value) {
 String[] fieldValues = (String[]) allParams.get(name);
 if(fieldValues==null){
 allParams.put(name, new String[]{value});
 }else{
 //如果不为空说明map集合里面已经有一份了 
 //'sex','male'界面又传来一个表单仍然需要保存
 //'sex','male',null 
 fieldValues = Arrays.copyOf(fieldValues, fieldValues.length+1);
 //再给新数组赋值
 fieldValues[fieldValues.length-1]=value;//给最后一个赋值最新的value
 allParams.put(name, fieldValues);//{'sex','male','male'}
 }

 } @Override
 public String getParameter(String name) {
   String[] values = (String[]) allParams.get(name);
   if(values != null){
     return values[0];
 }
   return null;
 } @Override
 public Map getParameterMap() {

    return allParams;
 } 
 public Map getAllParams() {
   return allParams;
 } public void setAllParams(Map allParams) {
   this.allParams = allParams;
 }
}}

如此在xxxServlet中

Attachment[] attachments = (Attachment[])request.getParameterMap().get("attachs");
 if(attachments != null){
 for(Attachment atta : attachments){
     System.out.println(atta.getName()+",已经被上传,文件类型是:"+atta.getContentType());
   a.addAttachments(atta);// GRASP模式中专家模式的运用
 }
 }

在baseServlet中悄悄得把httpServletRequest替换成MultipartServletRequest

这样在客户端的servlet就依赖于MultipartServletRequest request

@Override
public String getParameter(String name) {
  String[] values = (String[]) allParams.get(name);
  if(values != null){
    return values[0];
}
  return null;
} 
@Override
public Map getParameterMap() {

    return allParams;
}