2016-11-01 10 views
5

मैं एक सर्वर से छवियों को अपलोड करने, त्रुटियों और अपवाद हैंडलिंग शान से, के रूप में उपयोगकर्ता के लिए प्रदर्शित त्रुटि संदेश के साथ सक्षम होने के लिए चाहते हैं, और आदर्श रूप में केवल का उपयोग कर एक मौजूदा barebones वसंत बूट और Thymeleaf स्थापित करें।फ़ाइल अपलोड: अपलोड हो रहा है, सत्यापन, और अपवाद हैंडलिंग

उदाहरण परियोजना gs-uploading-files मैं एक सर्वर स्प्रिंग बूट और Thymeleaf उपयोग करने के लिए फ़ाइलों को अपलोड कर सकते हैं का उपयोग करना। Application.properties में मैंने spring.http.multipart.max-file-size=1MB और spring.http.multipart.max-request-size=1MB सेट किया है। हालांकि जब मैं 1 एमबी से बड़ी फ़ाइलों को अपलोड करता हूं तो कई सुरक्षा और सत्यापन समस्याएं अनसुलझे होती हैं।

  1. कोई भी फ़ाइल अपलोड की जा सकती है। उदाहरण के लिए, एक एचटीएमएल फाइल अपलोड की जा सकती है और इस प्रकार सर्वर पर होस्ट किया जा सकता है। फ़ाइलों को प्रकार से प्रतिबंधित कैसे किया जा सकता है? अनुरोध भेजने से पहले पृष्ठ में उन्हें सत्यापित किया जा सकता है? अगर मेरे पास छवियों को अपलोड करने के कई तरीके हैं तो मैं सभी मल्टीपार्टफ़ाइल को कैसे सत्यापित कर सकता हूं?

  2. उपयोगकर्ता बड़ी फ़ाइलों uploade को, स्प्रिंग और एम्बेडेड बिलाव के डिफ़ॉल्ट सीमाओं से परे का प्रयास कर सकते हैं। इससे org.springframework.web.multipart.MultipartException स्प्रिंग द्वारा नियंत्रित नहीं किया जाता है। अपलोड प्रयास से पहले फ़ाइल आकार को कैसे सत्यापित किया जा सकता है? यदि यह बाईपास किया गया है तो स्प्रिंग द्वारा पकड़ा गया कोई भी फ़ाइल अपलोड अपवाद हो सकता है, ताकि एक अच्छा त्रुटि संदेश प्रदर्शित हो सके?

  3. डिफ़ॉल्ट स्प्रिंग त्रुटि पृष्ठ सभी अपवादों के लिए फ़ॉलबैक के रूप में इस्तेमाल नहीं कर रहा है। MultipartException एक पूर्ण stacktrace के साथ एक टोमकैट अपवाद पृष्ठ देता है (लॉग 1 देखें)।


मैं कोशिश करते हैं और पाते हैं और समाधान का एक सेट को लागू करने की खोज की है।

handleFileUpload में संशोधन करके सामग्री प्रकार की जांच करें, सामग्री प्रकार की जांच करें, जो इसे विफल करते हैं: !file.getContentType().toLowerCase().startsWith("image")। क्या यह हमेशा वैध होगा? क्या एक दुर्भावनापूर्ण उपयोगकर्ता इसे बाईपास कर सकता है? और हर बार इसे जोड़ने के लिए याद रखने के लिए, मैं प्रत्येक मल्टीपार्टफाइल को कैसे देख सकता हूं?

@PostMapping("/") 
public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) 
     throws MultipartException, IllegalStateException { 

    if (file != null && file.getContentType() != null && !file.getContentType().toLowerCase().startsWith("image")) 
     throw new MultipartException("not img"); 

    storageService.store(file); 
    redirectAttributes.addFlashAttribute("message", 
      "You successfully uploaded " + file.getOriginalFilename() + "!"); 

    return "redirect:/"; 
} 

काम नहीं करता है एक @ExceptionHandler जोड़ा जा रहा है, यह बस कहा जाता हो जाता है कभी नहीं।

@ExceptionHandler({ SizeLimitExceededException.class, MultipartException.class, 
     java.lang.IllegalStateException.class }) 
public ModelAndView handleError(HttpServletRequest req, Exception e) { 
    // error("Request: " + req.getRequestURL() + " raised " + ex); 

    ModelAndView mav = new ModelAndView(); 
    mav.addObject("exception", e); 
    mav.addObject("url", req.getRequestURL()); 
    mav.addObject("timestamp", new Date()); 
    mav.addObject("error", e.getClass()); 
    mav.addObject("message", e.getMessage()); 
    mav.addObject("status", HttpStatus.INTERNAL_SERVER_ERROR); 
    mav.setViewName("error"); 
    return mav; 
} 

संख्या 3 सभी अपवादों पर वैश्विक अपवाद हैंडलर द्वारा हल किया जा सकता है। (this post में विस्तार से समझाया गया)। हालांकि, मुझे चिंता है कि यह एक नियंत्रक स्तर हैंडलर को खत्म कर सकता है।

package hello; 

import java.util.Date; 

import javax.servlet.http.HttpServletRequest; 

import org.springframework.core.annotation.AnnotationUtils; 
import org.springframework.http.HttpStatus; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 
import org.springframework.web.bind.annotation.ResponseStatus; 
import org.springframework.web.servlet.ModelAndView; 

@ControllerAdvice 
class GlobalDefaultExceptionHandler { 
    public static final String DEFAULT_ERROR_VIEW = "error"; 

    @ExceptionHandler(value = Exception.class) 
    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception { 
     // If the exception is annotated with @ResponseStatus rethrow it and let 
     // the framework handle it - like the OrderNotFoundException example 
     // at the start of this post. 
     // AnnotationUtils is a Spring Framework utility class. 
     if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) 
      throw e; 

     // Otherwise setup and send the user to a default error-view. 
     ModelAndView mav = new ModelAndView(); 
     mav.addObject("exception", e); 
     mav.addObject("url", req.getRequestURL()); 
     mav.addObject("timestamp", new Date()); 
     mav.addObject("error", e.getClass()); 
     mav.addObject("message", e.getMessage()); 
     mav.addObject("status", HttpStatus.INTERNAL_SERVER_ERROR); 
     mav.setViewName(DEFAULT_ERROR_VIEW); 
     return mav; 
    } 
} 

मैं this answer, जो अपवाद संभालती है लेकिन एक त्रुटि पृष्ठ रिटर्न का प्रयास किया है। मैं मूल पृष्ठ पर वापस लौटना चाहता हूं और एक अच्छा त्रुटि संदेश प्रदर्शित करना चाहता हूं।


प्रवेश करें 1:

HTTP Status 500 - Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 

type Exception report 

message Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 

description The server encountered an internal error that prevented it from fulfilling this request. 

exception 

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) 
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:648) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
root cause 

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:111) 
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:85) 
    org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:76) 
    org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1099) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:932) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:648) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
root cause 

java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 
    org.apache.catalina.connector.Request.parseParts(Request.java:2871) 
    org.apache.catalina.connector.Request.parseParameters(Request.java:3176) 
    org.apache.catalina.connector.Request.getParameter(Request.java:1110) 
    org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
root cause 

org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1292555) exceeds the configured maximum (1048576) 
    org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:811) 
    org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:256) 
    org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:280) 
    org.apache.catalina.connector.Request.parseParts(Request.java:2801) 
    org.apache.catalina.connector.Request.parseParameters(Request.java:3176) 
    org.apache.catalina.connector.Request.getParameter(Request.java:1110) 
    org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
note The full stack trace of the root cause is available in the Apache Tomcat/8.5.5 logs. 

Apache Tomcat/8.5.5 

उत्तर

1

अपने आवेदन में निम्नलिखित जोड़ने का प्रयास करें।गुण फ़ाइल आकार की सीमा निर्धारित करने के लिए:

spring.http.multipart.max-file-size=256KB 
spring.http.multipart.max-request-size=256KB 

स्रोत: https://spring.io/guides/gs/uploading-files/

+0

मैंने इन्हें सेट किया है (पैराग्राफ दो देखें)। जबकि वे बड़ी फ़ाइलों को अपलोड होने से रोकते हैं, वे समझदार त्रुटि संदेश या उपयोगकर्ता प्रतिक्रिया नहीं देते हैं, और फ़ाइल प्रकार को सत्यापित करने का कोई तरीका नहीं है। – aSemy

0

कैसे फ़ाइल प्रकारों की जाँच करने पर जवाब देने के लिए: मैं इस के लिए एक कस्टम सत्यापनकर्ता बनाया है।

सबसे पहले, एक एनोटेशन बनाएं:

import org.springframework.web.multipart.MultipartFile; 

import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 

public class ImageFileValidator implements ConstraintValidator<ValidImage, MultipartFile> { 

    @Override 
    public void initialize(ValidImage constraintAnnotation) { 

    } 

    @Override 
    public boolean isValid(MultipartFile multipartFile, ConstraintValidatorContext context) { 

     boolean result = true; 

     String contentType = multipartFile.getContentType(); 
     if (!isSupportedContentType(contentType)) { 
      context.disableDefaultConstraintViolation(); 
      context.buildConstraintViolationWithTemplate(
        "Only PNG or JPG images are allowed.") 
        .addConstraintViolation(); 

      result = false; 
     } 

     return result; 
    } 

    private boolean isSupportedContentType(String contentType) { 
     return contentType.equals("image/png") 
       || contentType.equals("image/jpg") 
       || contentType.equals("image/jpeg"); 
    } 
} 

अंत में एनोटेशन, लागू होते हैं::

public class CreateUserParameters { 

    @NotNull 
    @ValidImage 
    private MultipartFile image; 
... 
} 

मैं वसंत के साथ इस परीक्षण किया है

import javax.validation.Constraint; 
import javax.validation.Payload; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Target(ElementType.FIELD) 
@Retention(RetentionPolicy.RUNTIME) 
@Constraint(validatedBy = {ImageFileValidator.class}) 
public @interface ValidImage { 
    String message() default "Invalid image file"; 

    Class<?>[] groups() default {}; 

    Class<? extends Payload>[] payload() default {}; 
} 

इसके बाद, सत्यापनकर्ता ही बनाने बूट 1.5.10 (थाइमेलीफ के साथ भी)

अधिकतम फ़ाइल आकार के लिए, मैं एक समाधान भी देखना चाहूंगा जो "मानक त्रुटि तंत्र" के साथ काम करता है ताकि आप अन्य फ़ील्ड त्रुटियों की तरह त्रुटि प्रदर्शित कर सकें और उपयोगकर्ता उसकी गलती को सही कर सके।

संबंधित मुद्दे