代码之家  ›  专栏  ›  技术社区  ›  gstackoverflow

如何更换弹簧。http。多部分。运行时最大文件大小?

  •  1
  • gstackoverflow  · 技术社区  · 7 年前

    在里面 application.properties 我有:

    spring.http.multipart.maxFileSize
    spring.http.multipart.maxRequestSize
    

    但我希望能够在不重新启动应用程序的情况下更改此属性。

    有可能吗?

    1 回复  |  直到 7 年前
        1
  •  7
  •   Mikita Harbacheuski    7 年前

    在深入研究了源代码之后,我找到了一种方法来为 StandardServletMultipartResolver .

    标准ServletMultipartResolver 包裹 HttpServletRequest 具有 StandardMultipartHttpServletRequest 它使用标准的servlet api实现 request.getParts() MultipartConfigElement 由设置 ServletRegistrationBean 多部件配置 因为它包含我们感兴趣的属性。

    默认情况下 ServletRegistrationBean 得到 多部件配置 MultipartAutoConfiguration . 默认实现 多部件配置 不允许修改其属性,因此我们需要扩展此类以添加此类功能。进一步的实现取决于您是要根据每个请求修改参数,还是要为整个应用程序不时修改参数。

    根据请求

    MultipartConfigurationContext 存储特定请求的配置。 UpdateMultipartConfigurationFilter 设置给定请求的多部分属性。 UpdatableMultipartConfigElement 如果提供,则使用此信息。

    public class MultipartConfigurationContext {
    
        private static ThreadLocal<Integer> maxFileSize = new ThreadLocal<>();
    
        public static void setMaxFileSize(Integer val) {
            maxFileSize.set(val);
        }
    
        public static Integer getMaxFileSize() {
            return maxFileSize.get();
        }
    
        public static void clear() {
            maxFileSize.set(null);
        }
    }
    
    public class UpdatableMultipartConfigElement extends MultipartConfigElement {
    
        private final long maxFileSize;
    
        public UpdatableMultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) {
            super(location, maxFileSize, maxRequestSize, fileSizeThreshold);
            this.maxFileSize = maxFileSize;
        }
    
        @Override
        public long getMaxFileSize() {
            return MultipartConfigurationContext.getMaxFileSize() == null
                    ? maxFileSize : MultipartConfigurationContext.getMaxFileSize();
        }
    }
    
    public class UpdateMultipartConfigurationFilter extends OncePerRequestFilter implements Ordered {
    
        // this filter must be before OrderedHiddenHttpMethodFilter
        public static final int ORDER = FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER - 20000;
    
        @Override
        public int getOrder() {
            return ORDER;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
            // gets file size from request if present and sets it to MultipartConfigurationContext
            MultipartConfigurationContext.setMaxFileSize(150_000);
    
            filterChain.doFilter(request, response);
    
            MultipartConfigurationContext.clear();
        }
    }
    
    @Configuration
    @EnableConfigurationProperties(MultipartProperties.class)
    public class MultipartConfiguration {
    
        private final MultipartProperties multipartProperties;
    
        public MultipartConfiguration(MultipartProperties multipartProperties) {
            this.multipartProperties = multipartProperties;
        }
    
        @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultipartConfigElement multipartConfigElement = multipartProperties.createMultipartConfig();
            return new UpdatableMultipartConfigElement(multipartConfigElement.getLocation(), multipartConfigElement.getMaxFileSize(),
                    multipartConfigElement.getMaxRequestSize(), multipartConfigElement.getFileSizeThreshold());
        }
    
        @Bean
        public UpdateMultipartConfigurationFilter updateMultipartConfigurationFilter() {
            return new UpdateMultipartConfigurationFilter();
        }
    }
    

    全球地

    可更新的MultipartConfigElement 存储可以使用rest api调用在运行时更新的信息。

    public class UpdatableMultipartConfigElement extends MultipartConfigElement {
    
        private volatile long maxFileSize = -1;
    
        public UpdatableMultipartConfigElement(String location, long maxFileSize, long maxRequestSize, int fileSizeThreshold) {
            super(location, maxFileSize, maxRequestSize, fileSizeThreshold);
        }
    
        @Override
        public long getMaxFileSize() {
            return maxFileSize == -1 ? super.getMaxFileSize() : maxFileSize;
        }
    
        public void setMaxFileSize(long maxFileSize) {
            this.maxFileSize = maxFileSize;
        }
    }
    
    @Configuration
    @EnableConfigurationProperties(MultipartProperties.class)
    public class MultipartConfiguration {
    
        private final MultipartProperties multipartProperties;
    
        public MultipartConfiguration(MultipartProperties multipartProperties) {
            this.multipartProperties = multipartProperties;
        }
    
        @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultipartConfigElement multipartConfigElement = multipartProperties.createMultipartConfig();
            return new UpdatableMultipartConfigElement(multipartConfigElement.getLocation(), multipartConfigElement.getMaxFileSize(),
                    multipartConfigElement.getMaxRequestSize(), multipartConfigElement.getFileSizeThreshold());
        }
    }
    
    @RestController
    public class ConfigurationController {
    
        @Autowired
        private UpdatableMultipartConfigElement updatableMultipartConfigElement;
    
        @RequestMapping("/configuration")
        public void configuration(@RequestParam("maxFileSize") long maxFileSize) {
            updatableMultipartConfigElement.setMaxFileSize(maxFileSize);
        }
    
    }