文件上传的几种方式

文件上传的几种方式文件上传前端提交文件方式:请求方式为POST:<formaction=”uploadServlet”method=”post”/>使用file的表单域:<inputtype=”file”name=”file”/>用multipart/form-data

大家好,欢迎来到IT知识分享网。文件上传的几种方式"

文件上传

前端提交文件方式

  1. 请求方式为POST:< form action=”uploadServlet” method=”post” />
  2. 使用file的表单域:< input type=”file” name=”file” />
  3. 用multipart/form-data的请求编码方式:< form action=”uploadServlet” method=”post” enctype=”multipart/form-data” />
< form action="uploadServlet" method="post" enctype="multipart/form-data">
    File: < input type="file" name="file"/>
    < input type="submit" value="Submit"/>
 </ form>

方式一:JavaWeb 的HttpServlet

  1. 需要commons-fileupload-1.4.jar ,commons-io-2.11.0.jar, 使用HttpServletRequest时需要导入servlet-api的包

    commons-fileupload需要commons-io

  2. 需要在web.xml中添加servlet映射路径

public class FileServlet extends HttpServlet {
    @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       // 文件上传
       // 1. 判断上传的表单是普通表单还是文件表单	
       if(!ServletFileUpload.isMultipartContent(req)){
           return ; // 终止程序,说明这是一个普通的表单
       }	
       // 2. 创建上传文件的保存路径,建议在web-inf目录下,用户不能直接访问到
       String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
       File file = new File(uploadPath);
       // 目录不存在就创建这个目录,针对第一次上传时
       if(!file.exists()){
           file.mkdir(); // 创建目录
       }
       // 缓存,针对上传的文件较大时,存入缓存文件中,需要永久保存才转到upload文件夹下
  
       /**处理文件上传,一般都会通过流的方式进行操作,
        * 这里使用apache提供的组件进行实现 common-fileupload
        * */
       // 3. 获取DiskFileItemFactory对象,处理文件上传的路径或者大小限制,都有默认的
       DiskFileItemFactory factory = new DiskFileItemFactory();
       //4. 获取ServletFileUpload
       ServletFileUpload upload = new ServletFileUpload(factory);
       // 5. 处理上传的文件
           //把前端请求解析,封装成一个FileItem对象,需要从ServletFileUpload对象中获取
       try {
           List<FileItem> fileItems = upload.parseRequest(req);
           // 遍历每一个FileItem,表单中的每一项input被封装成一个FileItem对象
           for (FileItem fileItem : fileItems) {
               // 判断是否是普通类型,表单中的项
               if (fileItem.isFormField()){
                   // 普通类型
  
               }else {
                   //文件类型
                   // 获取到上传的文件的路径,进而获取到文件名
                   String filePath = fileItem.getName();
                   String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
                   // 通过uuid+fileName获取到新的文件名
                   String newFileName = UUID.randomUUID().toString() + fileName;
  
                   // 获取FileItem的流
                   InputStream in = fileItem.getInputStream();
  
                   // 把文件复制服务器上
                   String newFilePath = uploadPath+"/" + newFileName;
                       FileOutputStream out = new FileOutputStream(newFilePath);
  
                   byte[] buffer = new byte[1024];
                   int len;
                   while ((len = in.read(buffer)) != -1){
                       out.write(buffer,0,len);
                   }
  
                   // 关闭资源 , 清除fileItem的缓存
                   out.close();
                   in.close();
  
                   fileItem.delete();
               }
           }
       } catch (FileUploadException e) {
           e.printStackTrace();
       }
   }
}

MultipartResolver 是一个接口,它的实现类如下图所示,分为 CommonsMultipartResolver 类和 StandardServletMultipartResolver

方式二:CommonsMultipartResolver

基于Apache fileupload文件上传(了解)

在web阶段中我们用到的是 Apache fileupload这个组件来实现上传,在springmvc中对它进行了封装,让我们使用起来比较方便,但是底层还是由Apache fileupload来实现的。

  1. 需要commons-fileupload-1.4.jar ,commons-io-2.11.0.jar

    commons-fileupload需要commons-io

  2. 配置MultipartResolver处理器(文件上传解析器) bean的名字必须为:multipartResolver

<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8" />
        <property name="maxUploadSize" value="10485760000" />
        <property name="maxInMemorySize" value="40960" />
    </bean>

解析HttpServletRequest的方式

@RequestMapping(value = "/addproduct", method = RequestMethod.POST)
@ResponseBody
private Map<String, Object> addProduct(HttpServletRequest request) {
  Map<String, Object> modelMap = new HashMap<String, Object>();
  //接受前端参数的变量的初始化,包括商品、缩略图、详情图列表实体类
  ObjectMapper mapper = new ObjectMapper();
  Product product = null;
  String productStr = HttpServiceRequestUtil.getString(request, "productStr");
  MultipartHttpServletRequest multipartRequest = null;
  ImageHolder thumbnail = null;
  List<ImageHolder> productImgList = new ArrayList<ImageHolder>();
  //通用的解析器
  CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
  try {
      //若请求中存在文件流,则取出相关的文件(包括缩略图和详情图)
      //isMutipart是用来判断是否有文件上传
      if (multipartResolver.isMultipart(request)) {
          multipartRequest = (MultipartHttpServletRequest) request;
          //取出缩略图并构建ImageHolder对象
          CommonsMultipartFile thumbnailFile = (CommonsMultipartFile) multipartRequest.getFile("thumbnail");
          thumbnail = new ImageHolder(thumbnailFile.getOriginalFilename(), thumbnailFile.getInputStream());
          //取出详情图列表并构建List<ImageHolder>列表对象,最多支持六张图片上传
          for (int i = 0; i < IMAGEMAXCOUNT; i++) {
              CommonsMultipartFile productImgFile = (CommonsMultipartFile) multipartRequest.getFile("productImg" + i);
              if (productImgFile != null) {
                  ImageHolder productImg = new ImageHolder(productImgFile.getOriginalFilename(), productImgFile.getInputStream());
                  productImgList.add(productImg);
              } else {
                  //若取出的第i个详情图片文件流为空,则终止循环
                  break;
              }
          }
      } else {
          modelMap.put("success", false);
          modelMap.put("errMsg", "上传图片不能为空");
          return modelMap;
      }
  } catch (Exception e) {
      modelMap.put("success", false);
      modelMap.put("errMsg", e.toString());
      return modelMap;
  }
}

狂神文件输入输出的上传:

@Controller
public class FileController {
    //@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
    //批量上传CommonsMultipartFile则为数组即可
    @RequestMapping("/upload")
    public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {

        //获取文件名 : file.getOriginalFilename();
        String uploadFileName = file.getOriginalFilename();

        //如果文件名为空,直接回到首页!
        if ("".equals(uploadFileName)){
            return "redirect:/index.jsp";
        }
        System.out.println("上传文件名 : "+uploadFileName);

        //上传路径保存设置
        String path = request.getServletContext().getRealPath("/upload");
        //如果路径不存在,创建一个
        File realPath = new File(path);
        if (!realPath.exists()){
            realPath.mkdir();
        }
        System.out.println("上传文件保存地址:"+realPath);

        InputStream is = file.getInputStream(); //文件输入流
        OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流

        //读取写出
        int len=0;
        byte[] buffer = new byte[1024];
        while ((len=is.read(buffer))!=-1){
            os.write(buffer,0,len);
            os.flush();
        }
        os.close();
        is.close();
        return "redirect:/index.jsp";
    }
}

transferTo()形式上传:

/*
 * 采用file.Transto 来保存上传的文件
 */
@RequestMapping("/upload2")
public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

    //上传路径保存设置
    String path = request.getServletContext().getRealPath("/upload");
    File realPath = new File(path);
    if (!realPath.exists()){
        realPath.mkdir();
    }
    //上传文件地址
    System.out.println("上传文件保存地址:"+realPath);

    //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
    file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));

    return "redirect:/index.jsp";
}

方式三:StandardServletMultipartResolver

基于Servlet3.0以上版本的文件上传

  1. 需要依赖Servlet3.0以上版本

  2. 配置MultipartResolver处理器(文件上传解析器) bean的名字必须为:multipartResolver

    <bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
    
  3. Conreoller

@RequestMapping("/upload")
public Result<?> upload(MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException {
        Result<Object> result = new Result<>();
        result.setSuccess(false);
        //检查文件是否为空
        if (file.isEmpty()) {
            result.setMessage("上传文件不能为空");
            return result;
        }
		//检查文件大小  2097152 =2M
		if(file.getSize() > 2097152) {
            result.setMessage("文件大于2M");
            return result;
		}
		//检查是否是图片
		try {
			BufferedImage bi = ImageIO.read(file.getInputStream());
			if(bi == null){
                result.setMessage("不是图片");
            	return result;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
        // 获取文件存储路径(绝对路径),实际开发中,建议直接使用一个服务器的绝对地址
        String path = request.getServletContext().getRealPath("/WEB-INF/upload/");
//        System.out.println("服务器中的相对/WEB-INF/upload/完整路径:"+path);
        //获取上传文件后缀名
//        System.out.println("客户端上传的文件名:"+file.getOriginalFilename());
        String originalFilename = file.getOriginalFilename();
        String suff = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 获取文件名
        String fileName = UUID.randomUUID().toString().replaceAll("-","")+suff;
        // 创建文件实例
        File filePath = new File(path, fileName);
        // 如果文件目录不存在,创建目录
        if (!filePath.getParentFile().exists()) {
            filePath.getParentFile().mkdirs();
            System.out.println("创建目录" + filePath);
        }
        // 写入文件
        file.transferTo(filePath);

        result.setMessage("上传成功");
        result.setCode(200);
        result.setSuccess(true);
        return result;
    }

说明:如果前端的文件上传控件的name名和处理器方法参数名不一致可以使用该注解@RequestPart(“参数名”)或@RequestParam(“参数名”)

@RequestPart在前后端不分离的文件上传(基于表单文件上传)中和@RequestParam意义效果一致

@RequestPart可以处理特殊的数据格式,如JSON

一致:(实际开发中建议方式)

//前端:
<input type="file" name="file">
//后端:
public String upload(MultipartFile file, HttpServletRequest request){}

如果不一致:

//前端:
<input type="file" name="uploadFile">
//后端:
public String upload(@RequestParam("uploadFile") MultipartFile file, ....){}
//或
public String upload(@RequestPart("uploadFile") MultipartFile file, ....){}

多文件上传

多文件上传只需要把html代码中的多个< input type=”file” name=”file” >name属性设置为一样的就好。然后在controller中使用MultipartFile数组接受就行。

@RequestMapping(value="/upload", method=RequestMethod.POST)
public String fileUpload(@RequestParam("file") MultipartFile[] file){
   //遍历数组单个上传
    for (MultipartFile multipartFile : file) {
        
    }
}

补充:如果想要限制文件上传类型

解决思路:

1)基于前端,限制文件类型

2)基于后端,建议使用SpringMVC框架的拦截器进行拦截校验

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32524.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信