복붙노트

[SPRING] HiddenHttpMethodFilter가 활성화 된 후 Spring MVC 3.0.2를 사용하여 여러 파일 업로드하기

SPRING

HiddenHttpMethodFilter가 활성화 된 후 Spring MVC 3.0.2를 사용하여 여러 파일 업로드하기

중요 :이 질문은이 스레드에서 논의 된 문제가 이전 버전에서 수정되어 Spring의 후속 버전에서 더 이상 재현 할 수 없으므로이 질문은 3.0.4 이상의 모든 Spring 버전에서는 전혀 쓸모가 없습니다.

Spring 버전 3.0.2를 사용하고 있습니다. 파일 브라우저의 multiple = "multiple"속성을 사용하여 여러 파일을 업로드해야합니다.

<input type="file" id="myFile" name="myFile" multiple="multiple"/>

(그리고이 답변에 명시된 것과 같은 여러 파일 브라우저를 사용하지 않고, 실제로 시도해 보았습니다).

적절한 jQuery 플러그인 / 위젯을 사용하지 않으면 Internet Explorer 버전에서이 방법을 지원하지 않지만 지금 당장은별로 신경 쓰지 않습니다 (대부분의 다른 브라우저가이를 지원하므로).

이것은 commons fileupload와 잘 동작하지만 RequestMethod.POST와 RequestMethod.GET 메소드를 사용하는 것 외에도 Spring이 지원하고 RequestMethod.PUT과 RequestMethod.DELETE와 같은 다른 요청 메소드를 적절한 위치에 사용하고자합니다. 이를 위해, 나는 HiddenHttpMethodFilter를 사용하여 Spring을 구성했다.

파일 브라우저의 여러 파일을 선택하더라도 한 번에 하나의 파일 만 업로드 할 수 있습니다. Spring 컨트롤러 클래스에서 메소드는 다음과 같이 매핑된다.

@RequestMapping(method={RequestMethod.POST}, value={"admin_side/Temp"})
public String onSubmit(@RequestParam("myFile") List<MultipartFile> files, @ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) throws IOException, FileUploadException {
    for (MultipartFile file : files) {
        System.out.println(file.getOriginalFilename());
    }
}

요청 매개 변수 인 @RequestParam ( "myFile") List 파일조차도 MultipartFile 유형 목록입니다 (한 번에 하나의 파일 만 가질 수 있습니다).

이 블로그에서 여러 파일로 작업 할 가능성이 높은 전략을 찾을 수있었습니다. 나는 그것을 조심스럽게 지나쳤다.

해결책 2 - 원시 요청 사용 아래의 해결책은,

메서드를 재정의하려고 시도합니다.

protected MultipartParsingResult parseFileItems(List fileItems, String encoding){}

CommonsMultipartResolver 클래스를 확장하여 추상 클래스 CommonsFileUploadSupport의 인스턴스를 만들고,

package multipartResolver;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.fileupload.FileItem;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public final class MultiCommonsMultipartResolver extends CommonsMultipartResolver {

    public MultiCommonsMultipartResolver() {}

    public MultiCommonsMultipartResolver(ServletContext servletContext) {
        super(servletContext);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected MultipartParsingResult parseFileItems(List fileItems, String encoding) {
        Map<String, MultipartFile> multipartFiles = new HashMap<String, MultipartFile>();
        Map multipartParameters = new HashMap();

        // Extract multipart files and multipart parameters.
        for (Iterator it = fileItems.iterator(); it.hasNext();) {
            FileItem fileItem = (FileItem) it.next();

            if (fileItem.isFormField()) {
                String value = null;

                if (encoding != null) {
                    try {
                        value = fileItem.getString(encoding);
                    } catch (UnsupportedEncodingException ex) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Could not decode multipart item '" + fileItem.getFieldName()
                                    + "' with encoding '" + encoding + "': using platform default");
                        }

                        value = fileItem.getString();
                    }
                } else {
                    value = fileItem.getString();
                }

                String[] curParam = (String[]) multipartParameters.get(fileItem.getFieldName());

                if (curParam == null) {
                    // simple form field
                    multipartParameters.put(fileItem.getFieldName(), new String[]{value});
                } else {
                    // array of simple form fields
                    String[] newParam = StringUtils.addStringToArray(curParam, value);
                    multipartParameters.put(fileItem.getFieldName(), newParam);
                }
            } else {
                // multipart file field
                CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
                if (multipartFiles.put(fileItem.getName(), file) != null) {
                    throw new MultipartException("Multiple files for field name [" + file.getName()
                            + "] found - not supported by MultipartResolver");
                }

                if (logger.isDebugEnabled()) {
                    logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize()
                            + " bytes with original filename [" + file.getOriginalFilename() + "], stored "
                            + file.getStorageDescription());
                }
            }
        }

        return new MultipartParsingResult(multipartFiles, multipartParameters);
    }
}

결과는 parseFileItems () 메서드의 마지막 줄 (return 문) 즉

return new MultipartParsingResult(multipartFiles, multipartParameters);

첫 번째 매개 변수 multipartFiles가 HashMap에 의해 구현 된 Map 유형이기 때문에 컴파일 타임 오류가 발생하지만 실제로는 MultiValueMap 유형의 매개 변수가 필요합니다.

이것은 추상 클래스 인 CommonsFileUploadSupport 내에 정적 클래스의 생성자이며,

public abstract class CommonsFileUploadSupport {
    protected static class MultipartParsingResult {
        public MultipartParsingResult(MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {}
    }
}

그 이유는 다음과 같을 수 있습니다.이 해결책은 Spring 버전 2.5에 관한 것이고이 버전에는 부적절 할 수있는 Spring 버전 3.0.2를 사용하고 있습니다.

그러나 Map을 다음과 같은 코드 세그먼트에 표시된 것과 같이 다양한 방법으로 MultiValueMap으로 대체하려고했습니다.

MultiValueMap<String, MultipartFile>mul=new LinkedMultiValueMap<String, MultipartFile>();   

for(Entry<String, MultipartFile>entry:multipartFiles.entrySet()) {
    mul.add(entry.getKey(), entry.getValue());
}

return new MultipartParsingResult(mul, multipartParameters);

그러나 성공은 없습니다. Map을 MultiValueMap으로 대체하는 방법을 잘 모르겠습니다. 이렇게하면 브라우저가 Http 응답을 표시하고,

가능한 한 질문을 줄이고 불필요한 코드를 포함시키지 않았습니다.

HiddenHttpMethodFilter로 Spring을 설정 한 후에 어떻게 여러 파일을 업로드 할 수 있습니까?

이 블로그는 오랜 순위의 최우선 순위의 버그임을 나타냅니다.

버전 3.0.2 (3 이상)에 대한 해결책이 없다면 Spring 지원을 영구적으로 사용 중지하고 PUT, DELETE 및 기타 요청 메소드를 생략 한 블로그의 세 번째 솔루션에서 제안한대로 commons-fileupolad를 계속 사용해야합니다. .

MultiCommonsMultipartResolver 클래스의 parseFileItems () 메소드의 코드를 약간 변경하면 여러 파일을 업로드 할 수는 있지만 스프링 시도 3.0.2 (3 이상)에서 성공할 수는 없습니다.

해결법

  1. ==============================

    1.하나의 요청으로 여러 파일 업로드의 경우이 코드를 사용했습니다.

    하나의 요청으로 여러 파일 업로드의 경우이 코드를 사용했습니다.

    나는 그런 JSP를 가지고있다 :

    <p>Select files to upload. Press Add button to add more file inputs.</p>
    <table>
        <tr>
            <td><input name="files" type="file" multiple="true"/></td>
        </tr>
        <tr>
            <td><input name="files" type="file" multiple="true"/></td>
        </tr>
    </table>
    <br/><input type="submit" value="Upload" />
    

    파일 업로드 클래스 bean :

    import org.springframework.web.multipart.commons.CommonsMultipartFile;
    
    public class FileUploadForm {
    
        private CommonsMultipartFile [] files;
    
        public CommonsMultipartFile[] getFiles() {
            return files;
        }
    
        public void setFiles( CommonsMultipartFile[] files ) {
            this.files = files;
        }
    }
    

    제어 장치:

    @Controller
    @RequestMapping("/upload")
    public class FileUploadController {
    
        @RequestMapping(method = RequestMethod.GET)
        public String displayForm(ModelMap modelMap) {
            modelMap.addAttribute( new FileUploadForm() );
            return "uploadForm.jsp";
        }
    
        @RequestMapping(method = RequestMethod.POST)
        public String save(FileUploadForm uploadForm) {
            CommonsMultipartFile[] files = uploadForm.getFiles();
            if(files != null && files.length != 0) {
                for(MultipartFile file : files) {
                    System.out.println( file.getOriginalFilename() );
                }
            }
            return "success.jsp";
        }
    }
    

    이 코드는 하나의 요청으로 여러 파일을 업로드 할 수있게 해주 며, 각 파일에 대해 CommonsMultipartFile의 인스턴스를 가져올 수 있어야합니다.

  2. ==============================

    2.질문에서 언급 한 문제는 Spring 3.0.4에서 수정되었습니다. 따라서 해당 버전 이상을 사용했다면 (예, 현재 4.x.x입니다.)이 질문 / 답변을 더 이상 읽을 필요가 없습니다.

    질문에서 언급 한 문제는 Spring 3.0.4에서 수정되었습니다. 따라서 해당 버전 이상을 사용했다면 (예, 현재 4.x.x입니다.)이 질문 / 답변을 더 이상 읽을 필요가 없습니다.

  3. from https://stackoverflow.com/questions/13686757/uploading-multiple-files-using-spring-mvc-3-0-2-after-hiddenhttpmethodfilter-has by cc-by-sa and MIT license