spring mvc多文件上传

作者: geekerzhou | 来源:发表于2016-11-01 16:36 被阅读327次

    适用 spring mvc, spring boot

    Controller代码:

    @PostMapping("/files")
    @ResponseStatus(HttpStatus.CREATED)
    public List<String> handleFileUpload(@RequestParam("files") MultipartFile[] files, String dir) {
        //获取项目当前路径
        String projectFolder = System.getProperty("user.dir");
        
        List<String> publicPathList = Lists.newArrayList();
        for (MultipartFile file : files) {
            //根据需求提供上传路径
            String publicPath = "/upload/" + dir + "/" + file.getOriginalFilename();
            File realFile = new File(projectFolder + publicPath);
            
            file.transferTo(realFile);
            
            publicPathList.add(publicPath);
        }
        return publicPathList;
    }
    

    html代码:

    <form action="/files" method="post" encType="multipart/form-data">
        <!--注意accept属性不要写成*/*,会卡成翔,根据需求写对应的mime,别偷懒-->
        <input type="file" name="files" multiple="multiple" accept="image/jpg,image/jpeg,image/png" />
        <!--和文件一起提交别的参数-->
        <input type="hidden" name="dir" value="avatar" />
    </form>
    

    文件处理 :

    可以利用MultipartFile的getInputStream方法对文件进一步处理,举个栗子,图片压缩:

    //使用阿里的图片处理库:SimpleImage
    private void scale(InputStream inputStream, FileOutputStream outputStream) throws SimpleImageException{
        //这里默认最大宽度1024,最大高度1024了,可根据需求做成参数
        ScaleParameter scaleParam = new ScaleParameter(1024,1024);
        WriteParameter writeParam = new WriteParameter();
    
        ImageRender rr = new ReadRender(inputStream);
        ImageRender sr = new ScaleRender(rr, scaleParam);
        ImageRender wr = null;
        try {
            wr = new WriteRender(sr, outputStream, ImageFormat.JPEG, writeParam);
            wr.render();
        } catch (SimpleImageException e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
            try {
                if (wr != null) {
                    wr.dispose();
                }
            } catch (SimpleImageException e) {
                // ignore ...
            }
        }
    }
    

    调用

    scale(file.getInputStream(), new FileOutputStream(realFile));
    

    踩坑

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>simpleimage</artifactId>
        <version>1.2.3</version>
        <!--使用spring boot时会和默认引入的log4j-over-slf4j冲突,需要干掉-->
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--SimpleImage依赖的javax.media.jai.core在官方的maven仓库中并没有,需要引用spring提供的-->
    <dependency>
        <groupId>javax.media.jai</groupId>
        <artifactId>com.springsource.javax.media.jai.core</artifactId>
        <version>1.1.3</version>
    </dependency>
    

    代码组织:

    建议将文件上传处理部分抽出来,如:

    FileService //文件处理接口
        LocalFileServiceImpl    //本地存储文件处理实现
        QiniuFileServiceImpl    //七牛云存储文件处理实现
    

    上传路径和可访问路径可放到配置文件中,贴下spring-boot环境完整本地文件处理实现供参考:

    LocalFileServiceImpl

    @Service
    public class LocalFileServiceImpl implements FileService {
    
        @Resource
        private UploadProperties uploadProperties;
    
        @Override
        public String upload(MultipartFile file, String dir, int maxWidth, int maxHeight) throws Exception {
            String projectFolder = System.getProperty("user.dir");
            String folderAndName = getFileUriGeneratedPart(file, dir);
            String path = projectFolder + uploadProperties.getPath() + folderAndName;
    
            File realFile = new File(path);
            if(!realFile.getParentFile().exists()) {
                if(!realFile.getParentFile().mkdirs()) {
                    throw new Exception("创建文件上传目录失败");
                }
            }
            try {
                scale(file.getInputStream(), new FileOutputStream(realFile), maxWidth, maxHeight);
            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
            return uploadProperties.getPublicPath() + folderAndName;
        }
    
        private String getFileUriGeneratedPart(MultipartFile file, String dir) {
            return "/" + dir + "/"+ genRandomString(16) +
                    "." + getExtensionName(file.getOriginalFilename());
        }
    
        //缩放用户上传图片,减小宽带占用
        private void scale(InputStream inputStream, FileOutputStream outputStream, int maxWidth, int maxHeight) throws SimpleImageException{
            ScaleParameter scaleParam = new ScaleParameter(maxWidth, maxHeight);
            WriteParameter writeParam = new WriteParameter();
    
            ImageRender rr = new ReadRender(inputStream);
            ImageRender sr = new ScaleRender(rr, scaleParam);
            ImageRender wr = null;
            try {
                wr = new WriteRender(sr, outputStream, ImageFormat.JPEG, writeParam);
                wr.render();
            } catch (SimpleImageException e) {
                throw e;
            } finally {
                IOUtils.closeQuietly(inputStream);
                IOUtils.closeQuietly(outputStream);
                try {
                    if (wr != null) {
                        wr.dispose();
                    }
                } catch (SimpleImageException e) {
                    // ignore ...
                }
    
            }
        }
    
        private static String getExtensionName(String filename) {
            if (StringUtils.isNotBlank(filename)) {
                int dot = filename.lastIndexOf('.');
                if ((dot >-1) && (dot < (filename.length() - 1))) {
                    return filename.substring(dot + 1).toLowerCase();
                }
            }
            return filename;
        }
        
        private static String genRandomString(int length) {
            String base = "abcdefghijklmnopqrstuvwxyz0123456789";
            Random random = new Random();
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(base.length());
                sb.append(base.charAt(number));
            }
            return sb.toString();
        }
    }
    

    以上代码移除了自定义的异常类

    UploadProperties

    @Component
    @ConfigurationProperties("custom.upload")
    public class UploadProperties {
        private String path;
        private String publicPath;
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    
        public String getPublicPath() {
            return publicPath;
        }
    
        public void setPublicPath(String publicPath) {
            this.publicPath = publicPath;
        }
    }
    

    spring boot配置 application-local.yml

    custom.upload:
      path: /src/upload
      public-path: /upload

    相关文章

      网友评论

        本文标题:spring mvc多文件上传

        本文链接:https://www.haomeiwen.com/subject/ygvmuttx.html