spring限制上传文件的类型(含代码)

为了安全,有时我们需要限制前端上传文件的类型,这个功能可以结合Spring的拦截器和Hutool的文件类型判断来完成。

我们实现如下功能:

  1. 整个项目默认仅允许一些常见文件类型的上传,比如xlsx等
  2. 如果某个接口有具体要求,还可以在接口级指定该接口额外允许上传的文件类型

首先,我们需要加载hutool包:

            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <!-- 版本号去官网找最新的就行 -->
                <version>5.8.27</version>
            </dependency>

下面是代码,实现了上面的功能:


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author 
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AdditionAllowUploadFileTypes {
    String[] value() default "";
}


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
 * 默认支持上传:
 * 1. 文档类: "xlsx", "xls", "docx", "doc", "pdf", "txt"
 * 2. 图片/视频类: "jpg", "jpeg", "png", "bmp", "mp4"
 * 3. 压缩包:zip
 *
 * @author 
 */
@ConfigurationProperties(prefix = "myservice.filetype")
@Data
public class FileTypeProperties {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileTypeProperties.class);

    /**
     * 默认允许的文件类型
     *
     * @see cn.hutool.core.io.FileTypeUtil
     */
    private List<String> defaultAllowTypes = Lists.newArrayList(
            "xlsx", "xls", "docx", "doc", "pdf", "txt",
            "jpg", "jpeg", "png", "bmp", "mp4",
            "zip");

    /**
     * 自定义支持的扩展类型
     *
     * @see cn.hutool.core.io.FileTypeUtil
     */
    private List<String> additionalAllowTypes;

    private Set<String> allowedTypes;

    @PostConstruct
    public void preSetAllowedTypes() {
        allowedTypes = new HashSet<>();

        if (CollectionUtil.isNotEmpty(defaultAllowTypes)) {
            for (String type : defaultAllowTypes) {
                if (StrUtil.isNotBlank(type)) {
                    allowedTypes.add(type.toLowerCase(Locale.ROOT));
                }
            }
        }
        if (CollectionUtil.isNotEmpty(additionalAllowTypes)) {
            for (String type : additionalAllowTypes) {
                if (StrUtil.isNotBlank(type)) {
                    allowedTypes.add(type.toLowerCase(Locale.ROOT));
                }
            }
        }
        LOGGER.info("File Allowed Types 初始化完成!");
    }
}


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpStatus;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 限制上传文件类型
 *
 * @author 
 */
public class FileTypeFilter implements HandlerInterceptor {
    private final FileTypeProperties fileTypeProperties;

    public FileTypeFilter(FileTypeProperties fileTypeProperties) {
        this.fileTypeProperties = fileTypeProperties;
    }

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request,
                             @NonNull HttpServletResponse response,
                             @NonNull Object handler) throws Exception {
        if (!(request instanceof MultipartHttpServletRequest)) {
            return true;
        }

        Map<String, MultipartFile> allFiles = ((MultipartHttpServletRequest) request).getFileMap();
        List<String> notAllowedFiles = getNotAllowedFiles(handler, allFiles);

        if (CollUtil.isNotEmpty(notAllowedFiles)) {
            String message = CharSequenceUtil.format("不被允许的文件类型!不被允许的文件列表如下:{}", notAllowedFiles);
            ServletUtil.write(response, message, MediaType.TEXT_PLAIN_VALUE));
            return false;
        }

        return true;
    }

    private List<String> getNotAllowedFiles(Object handler, Map<String, MultipartFile> allFiles) throws IOException {
        List<String> notAllowedFilenames = null;
        for (MultipartFile file : allFiles.values()) {
            if (!isAllowedFile(file, handler)) {
                if (notAllowedFilenames == null) {
                    notAllowedFilenames = new ArrayList<>();
                }
                notAllowedFilenames.add(file.getOriginalFilename());
            }
        }
        return notAllowedFilenames;
    }

    boolean isAllowedFile(MultipartFile file, Object handler) throws IOException {
        String fileName = file.getOriginalFilename();
        try (InputStream in = file.getInputStream()) {
            String type = FileTypeUtil.getType(in, fileName);
            if (StringUtils.isBlank(type)) {
                // 无法通过文件头或者扩展名识别文件类型。
                return false;
            }

            String extType = FileUtil.extName(fileName);
            if (StringUtils.isBlank(extType)) {
                // 后缀读不到类型,直接拒绝
                return false;
            }

            // 文件头类型和后缀类型都要满足白名单
            if (CollectionUtils.containsAll(fileTypeProperties.getAllowedTypes(),
                    Lists.newArrayList(type.toLowerCase(Locale.ROOT), extType.toLowerCase(Locale.ROOT)))) {
                return true;
            }

            String[] additionAllowUploadFileTypes = getAdditionAllowUploadFileTypes(handler);
            return Arrays.stream(additionAllowUploadFileTypes)
                    .anyMatch(type::equalsIgnoreCase) &&
                    Arrays.stream(additionAllowUploadFileTypes)
                            .anyMatch(extType::equalsIgnoreCase);
        }
    }

    private String[] getAdditionAllowUploadFileTypes(Object handle) {
        String[] res = new String[0];
        if (!(handle instanceof HandlerMethod)) {
            return res;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handle;
        if (handlerMethod.hasMethodAnnotation(AdditionAllowUploadFileTypes.class)) {
            AdditionAllowUploadFileTypes types = handlerMethod.getMethodAnnotation(AdditionAllowUploadFileTypes.class);
            if (types != null) {
                String[] allowedTypes = types.value();
                if (allowedTypes != null) {
                    res = allowedTypes;
                }
            }
        }
        return res;
    }
}

使用方法:
项目中可以在application.yaml中指定项目级别额外允许的文件类型

  1. 默认允许的类型:"xlsx", "xls", "docx", "doc", "pdf", "txt", "jpg", "jpeg", "png", "bmp", "mp4","zip",可以通过myservice.filetype.default-allow-types变量来覆盖
  2. 如果觉得上面的类型没问题,只是想新增几个韦德类型,可以使用下面的配置:
myservice:
  filetype: 
    additional-allow-types: 
      - xxx
  1. 接口级的可以在接口上使用注解@AdditionAllowUploadFileTypes("xxx")来额外允许指定类型的文件上传。
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Spring中,您可以使用MultipartFile接口上传文件。以下是一个示例代码: ``` @PostMapping("/upload") public String fileUpload(@RequestParam("file") MultipartFile file) { try { // 存储文件 byte[] bytes = file.getBytes(); Path path = Paths.get("文件存储路径" + file.getOriginalFilename()); Files.write(path, bytes); return "文件上传成功"; } catch (IOException e) { e.printStackTrace(); return "文件上传失败"; } } ``` 请注意,在实际应用中,您需要调整文件存储路径以符合您的需求。此外,您还可以执行其他操作,例如验证文件类型和大小等。 ### 回答2: 代码生成是指通过程序自动生成相关代码,以减少手动编写代码的工作量。在Spring框架中,文件上传是一个常见的功能需求,可以通过代码生成来实现。 首先,我们需要使用Spring提供的MultipartFile类型来接收上传的文件。在控制层,我们可以使用@RequestParam注解将上传的文件绑定到MultipartFile对象上。接着,我们需要创建一个File对象,用于保存上传的文件。可以使用MultipartFile的transferTo()方法将文件保存到指定位置。最后,我们可以通过调用File对象的getAbsolutePath()方法获取文件的绝对路径。 在Spring中,Spring Boot提供了自动配置的功能,可以简化文件上传的配置过程。我们只需要在application.properties文件中配置上传文件的保存路径即可。Spring Boot会自动根据配置的路径创建对应的文件夹,并将上传的文件保存在该路径下。 另外,为了更好地处理文件上传功能,我们可以封装一个工具类来处理文件上传的逻辑。该工具类可以包括上传文件的方法、保存文件的方法等。在上传文件时,可以根据文件的类型进行校验,判断是否符合要求。可以通过设置最大文件大小来限制上传文件的大小。在保存文件时,可以添加一些附加的处理逻辑,比如生成缩略图等。 总之,通过代码生成可以实现Spring文件上传功能。使用Spring提供的MultipartFile类型,我们可以方便地接收上传的文件。结合Spring Boot的自动配置,我们可以简化文件上传的配置过程。封装一个工具类,可以更好地处理文件上传的逻辑。通过代码生成,我们可以减少手动编写代码的工作量,提高开发效率。 ### 回答3: 代码生成是一种自动化的软件开发方式,可以根据特定的要求和配置文件来生成相应的代码。在Spring框架中,文件上传是常见的需求之一。 首先,需要在Spring配置文件中进行相应的配置,控制文件上传的相关参数,例如允许上传的文件类型、大小限制等。配置完成后,代码生成工具会根据配置文件自动生成相应的代码。 在代码生成器中,需要定义上传文件的处理逻辑。通常涉及到以下几个步骤: 1. 创建一个Controller来处理文件上传请求。可以使用Spring提供的MultipartFile类来处理上传的文件。 2. 在Controller中,根据业务需要,进行文件上传的处理逻辑。可以通过MultipartFile对象的方法获取文件名、文件类型等信息,并进行相应的校验。 3. 使用Spring的ResourceLoader类来将上传的文件保存到指定的位置。可以利用ResourceLoader的方法将上传的文件保存到指定的路径或者存储到数据库中。 4. 在前端页面中,通过表单或者其他方式触发文件上传请求。可以使用Spring提供的Form标签或者MultipartFile类来实现文件上传。 以上只是一个简单的代码生成示例,实际开发中还需要考虑更多的细节和异常处理。通过代码生成,可以减少手动编写繁琐的文件上传代码的过程,提高开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值