2013-02-07 5 views
0

웹 클라이언트에서 다중 MVC 컨트롤러로 multipart 폼 데이터를 업로드하려고합니다. 나는 HTML 양식을 통해 양식 업로드를하고 있지 않다 이것은 내가 무엇을 달성하고자되지 않습니다 :다중 파트 폼 데이터를 클라이언트에 업로드하는 방법

curl -v -X POST -F "[email protected]" -F "id=12345" -F "name=Walmart" http://localhost:8080/api/cardprovider/logo 

주의 사항 : 나는 curl 명령을 다음의 "봄"구현을 검색합니다.

지금 내 질문은 :

  • 당신이로이 blog 설명이 아파치 커먼즈 HttpClient를를 사용 하시겠습니까?
  • 또는 "Spring"종류의 Magic 라이브러리가 있습니까? 도와주세요.

나는 스프링 라이브러리를 사용하여 해결책을 찾기 위해 많은 시간을 보냈지 만, 스프링 매뉴얼의 모든 예제는 html 폼 업로드를 참조하거나 매우 기본적이고 기본 텍스트만으로 간단하다.

스프링이 상당히 새로워졌지만, 스프링에서 뽑은 사람들이 멀티 파트 데이터를 업로드하는 것이 더 쉬운 것으로 생각한다면 놀랄 것입니다. 양식에서 보낸다면). 위의 컬 명령은 다음과 같은 서버 측 코드를 성공적으로 작동하고

:

컨트롤러 :

:

@Controller 
@RequestMapping("/api/cardprovider/logo") 
public class CardproviderLogoResourceController { 

    @Resource(name = "cardproviderLogoService") 
    private CardproviderLogoService cardproviderLogoService; 

    /** 
    * Used to upload a binary logo of a Cardprovider through a Multipart request. The id is provided as form element. 
    * <p/> 
    * Example to upload a file using curl: 
    * curl -v -X POST -F "[email protected]" -F "id=12345" -F "name=Walmart" http://localhost:8080/api/cardprovider/logo 
    * <p/> 
    * 
    * @param logo the Multipart request 
    * @param id the Cardprovider id 
    * @param name the Cardprovider name 
    */ 
    @RequestMapping(value = "", method = RequestMethod.POST) 
    @ResponseStatus(HttpStatus.NO_CONTENT) 
    public void storeCardproviderLogo(@RequestParam(value = "logo", required = false) MultipartFile logo, 
            @RequestParam(value = "name") String name, 
            @RequestParam(value = "id") String id) throws IOException { 

    cardproviderLogoService.storeLogo(logo, id, name); 
    } 
} 

그리고 여기에는 GridFS 데이터베이스에 멀티 파트 요청을 저장하는 내 서비스 클래스입니다

서비스 :

@Service 
public class CardproviderLogoService { 

    @Autowired 
    GridFsOperations gridOperation; 

    /** 
    * Create the logo in MongoDB GridFS with the data returned from the Multipart 
    * <p/> 
    * 
    * @param logo the MultipartFile content 
    * @param id  the Cardprovider id 
    * @param name the Cardprovider name 
    * @return true if the image can be saved in the database, else false 
    */ 
    public Boolean storeLogo(MultipartFile logo, String id, String name) { 
    Boolean save_state = false; 

    BasicDBObject metadata = new BasicDBObject(); 
    metadata.put("cardproviderId", id); 
    metadata.put("cardproviderName", name); 
    metadata.put("contentType", logo.getContentType()); 
    metadata.put("fileName", createLogoFilename(name, logo.getOriginalFilename())); 
    metadata.put("originalFilename", logo.getOriginalFilename()); 
    metadata.put("dirShortcut", "cardproviderLogo"); 
    metadata.put("filePath", "/resources/images/cardproviders/logos/"); 

    try { 
     gridOperation.store(logo.getInputStream(), 
       metadata.getString("fileName").toLowerCase().replace(" ", "-"), 
       metadata); 
     save_state = true; 
    } catch (Exception ex) { 
     Logger.getLogger(CardproviderLogoService.class.getName()) 
       .log(Level.SEVERE, "Storage of Logo failed!", ex); 
    } 

    return save_state; 
} 

/** 
* Creates the new filename before storing the file in MongoDB GridFS. The filename is created by taking the 
* name of the Cardprovider, lowercase the name and replace the whitespaces with dashes. At last the file 
* extension is added that was provided by the original filename. 
* <p/> 
* 
* @param name the Cardprovider name 
* @param originalFilename the original filename 
* @return the new filename as String 
*/ 
private String createLogoFilename(String name, String originalFilename) { 
    String cpName = name.toLowerCase().replace(" ", "-"); 

    String extension = ""; 
    int i = originalFilename.lastIndexOf('.'); 
    if (i > 0 && i < originalFilename.length() - 1) { 
     extension = originalFilename.substring(i + 1).toLowerCase(); 
    } 
    return cpName + "." + extension; 
    } 
} 

감사합니다. 요 UR 도움과 종류에 관해서, 크리스

솔루션

나는이 문제를 다음과 같은 방법으로 해결할 수 있습니다. 입력 양식을 사용하고 파일을 전송하기 위해 RestController에 대한 연결을 구축하는 HtmlController가 있습니다. 내가 아는 봄

@RequestMapping(value = "/add", method = RequestMethod.POST) 
public String addCardprovider(
     @ModelAttribute("cardproviderAttribute") Cardprovider cardprovider, 
     Model model) { 

    // Prepare acceptable media type 
    List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>(); 
    acceptableMediaTypes.add(MediaType.APPLICATION_XML); 

    // Prepare header 
    HttpHeaders headers = new HttpHeaders(); 
    headers.setAccept(acceptableMediaTypes); 
    // Pass the new person and header 
    HttpEntity<Cardprovider> entity = new HttpEntity<Cardprovider>(
      cardprovider, headers); 

    // Send the request as POST 
    try { 
     // Save Cardprovider details 
     ResponseEntity<Cardprovider> response = restTemplate.exchange(
       "http://localhost:8080/api/cardprovider", HttpMethod.POST, 
       entity, Cardprovider.class); 

     // Save Cardprovider logo 
     String tempDir = System.getProperty("java.io.tmpdir"); 
     File file = new File(tempDir + "/" + cardprovider.getLogo().getOriginalFilename()); 
     cardprovider.getLogo().transferTo(file); 

     MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>(); 
     parts.add("id", response.getBody().getId()); 
     parts.add("name", response.getBody().getName()); 
     parts.add("logo", new FileSystemResource(file)); 

     restTemplate.postForLocation("http://localhost:8080/api/cardprovider/logo", parts); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    // This will redirect to /web/cardprovider/getall 
    return "redirect:/web/cardprovider/getall"; 
} 

답변

0

아무것도 : 여기

는 HtmlController의 방법이다. 이러한 작업을 위해 Apache Commons HttpClient를 사용하는 것이 내 서클에서 일반적인 관행입니다.

업데이트 봄이에 대한 지원을 제공합니다 물론

는 - 죄송합니다, 나는 가장 눈에 띄는을 간과 : RestTemplate를!

XML :

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> 
<property name="messageConverters"> 
    <list> 
    <bean class="org.springframework.http.converter.StringHttpMessageConverter" /> 
    <bean class="org.springframework.http.converter.FormHttpMessageConverter" /> 
    </list> 
</property> 
</bean> 

자바 :

MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>(); 
form.add("key", value); 
... 
form.add("file", new FileSystemResource(file)); 
restTemplate.postForLocation(url, form); 
+0

안녕 마르셀, 귀하의 답변을 주셔서 감사합니다.그것은 평가 받는다. 나는 스프링이 이것을위한 해결책을 가지고 있다고 생각했다. 그러나 실제로는 그렇지 않은 것처럼 보입니다. JAX-RS (Jersey)에 대한 일부 기능에서는 Spring이 여전히 부족한 것처럼 보입니다. 대규모 XML 파일의 SAX 구문 분석과 같이 대용량 데이터를 처리하기 위해 Jersey를 Spring과 혼합하는 것이 일반적입니까? 가능한 적은 라이브러리를 사용하고 싶지만 바이너리 전송 및 대용량 파일 구문 분석이 필요한 특정 기능이 필요합니다. –

+0

@ChristopherArmstrong, grrrh 나는 가장 명백한 것을 놓쳤다. 나는 나의 대답을 업데이트 할 것이다. 의견에 귀하의 질문 (들)에 관해서는, 그것은 다릅니다. 이전 프로젝트는 Spring WebMVC를 기반으로했습니다. 따라서 JAX-RS가 이미 필요합니다 (추가 JAX-RS 라이브러리가 필요 없음). 현재 프로젝트에서는 GWT가 있으며 SOAP API도 제공합니다. SOAP의 경우 JAX-RS도 구현하는 CXF를 사용합니다. 다시 말하지만 Jersey는 CXF로 REST 서비스를 구축 할 필요가 없습니다. –

+0

답장을 보내 주셔서 감사합니다. 스프링 쉴드로 문제를 해결할 수는 있지만 jsr 311 준수 또는 기타 특수 요구 사항이 필요한 경우 다른 휴식 프레임 워크에서 혼합해야하는 경우도 있습니다. 면허의 관점에서 보면 cxf는 더 많은 자유와 저지를 제공합니다. 그러나 저지는 최고의 문서를 가지고 있습니다. 모두 봄에 통합 될 수 있습니다. –

관련 문제