• 文件上传时,MultipartFile.transferTo() 方法报 FileNotFoundException


    Spring Upload File 报错FileNotFoundException

    环境:
        Springboot 2.0.4
        JDK1.8
        内嵌 Apache Tomcat/8.5.32

    1、前端代码

    前端上传网页表单,enctype 和 input 的type=file 即可,使用单文件上传举例:

    <form enctype="multipart/form-data" method="POST"
        action="/file/fileUpload">
        图片<input type="file" name="file" />
        <input type="submit" value="上传" />
    </form>

    2、后端代码

    @RestController
    @RequestMapping("/file")
    public class UploadFileController {
        @Value("${file.upload.path}")
        private String path = "upload/";
    
        @RequestMapping(value = "fileUpload", method = RequestMethod.POST)
        @ResponseBody
        public String fileUpload(@RequestParam("file") MultipartFile file) {
            if (file.isEmpty()) {
                return "false";
            }
            String fileName = file.getOriginalFilename();
            File saveFile = new File(path + "/" + fileName);
            if (!saveFile.getParentFile().exists()) { 
                saveFile.getParentFile().mkdirs();
            }
            try {
                file.transferTo(saveFile); // 保存文件
                return "true";
            } catch (Exception e) {
                e.printStackTrace();
                return "false";
            }
        }
    }

    3、问题分析与解决

    按照上面配置运行时,在保存文件 file.transferTo(saveFile) 报错

    3.1 问题原因分析:

    saveFile是相对路径,指向 upload/doc20170816162034_001.jpg
    file.transferTo 方法调用时,判断如果是相对路径,则使用temp目录,为父目录
    因此,实际保存位置为 C:UsersxxxxAppDataLocalTemp omcat.372873030384525225.8080workTomcatlocalhostROOTuploaddoc20170816162034_001.jpg

    一则,位置不对,二则没有父目录存在,因此产生上述错误。

    3.2 问题解决

    transferTo 传入参数 定义为绝对路径
    @RestController
    @RequestMapping("/file")
    public class UploadFileController {
        @Value("${file.upload.path}")
        private String path = "upload/";
    
        @RequestMapping(value = "fileUpload", method = RequestMethod.POST)
        @ResponseBody
        public String fileUpload(@RequestParam("file") MultipartFile file) {
            if (file.isEmpty()) {
                return "false";
            }
            String fileName = file.getOriginalFilename();
            File dest = new File(new File(path).getAbsolutePath()+ "/" + fileName);
            if (!dest.getParentFile().exists()) { 
                dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(dest); // 保存文件
                return "true";
            } catch (Exception e) {
                e.printStackTrace();
                return "false";
            }
        }
    }
    也可以 file.getBytes() 获得字节数组,OutputStream.write(byte[] bytes)自己写到输出流中。

    4、补充方法

    application.properties 中增加配置项
    spring.servlet.multipart.location= # Intermediate location of uploaded files.

    关于上传文件的访问

    增加一个自定义的ResourceHandler把目录公布出去

    // 写一个Java Config 
    @Configuration
    public class webMvcConfig implements org.springframework.web.servlet.config.annotation.WebMvcConfigurer{
        // 定义在application.properties
        @Value("${file.upload.path}")
        private String path = "upload/";
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            String p = new File(path).getAbsolutePath() + File.separator;//取得在服务器中的绝对路径
            System.out.println("Mapping /upload/** from " + p);
            registry.addResourceHandler("/upload/**") // 外部访问地址
                .addResourceLocations("file:" + p)// springboot需要增加file协议前缀
                .setCacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES));// 设置浏览器缓存30分钟
        }
    }

    application.properties 中 file.upload.path=upload/

    实际存储目录
    D:/upload/2019/03081625111.jpg

    访问地址(假设应用发布在http://www.a.com/)
    http://www.a.com/upload/2019/03081625111.jpg

    在Controller中增加一个RequestMapping,把文件输出到输出流中

    @RestController
    @RequestMapping("/file")
    public class UploadFileController {
        @Autowired
        protected HttpServletRequest request;
        @Autowired
        protected HttpServletResponse response;
        @Autowired
        protected ConversionService conversionService;
    
        @Value("${file.upload.path}")
        private String path = "upload/";    
    
        @RequestMapping(value="/view", method = RequestMethod.GET)
        public Object view(@RequestParam("id") Integer id){
            // 通常上传的文件会有一个数据表来存储,这里返回的id是记录id
            UploadFile file = conversionService.convert(id, UploadFile.class);// 这步也可以写在请求参数中
            if(file==null){
                throw new RuntimeException("没有文件");
            }
            
            File source= new File(new File(path).getAbsolutePath()+ "/" + file.getPath());
            response.setContentType(contentType);
    
            try {
                FileCopyUtils.copy(new FileInputStream(source), response.getOutputStream());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
  • 相关阅读:
    javascript对话框
    重构之美-走在Web标准化设计的路上[复杂表单]
    xhtml标准下的height:100%
    javascript简洁的LightBox
    Web标准学习书籍推荐
    Email
    jQuery插件Cookie
    Linq to sql 简单性能差异指引 2 (转)
    jQuery Impromptu
    UI
  • 原文地址:https://www.cnblogs.com/cndarren/p/12558348.html
Copyright © 2020-2023  润新知