2015-02-09 20 views
13

RestTemplate ile Raspberry Pi ve Jetty ile bir dosya yüklemeye çalışıyorum. Ben Bu webapp aynı özelliğe sahip gerekiyordu yöntemdir RestTemplate Spring-mvc ile Çoklu formlu form verileri nasıl gönderilir

bukle

curl --form [email protected]/home/pi/src/CreateNewFolderServlet.java --form press=OK localhost:2222/pi/GetFileServlet?path="/media/"

ile başarılı bir şekilde yapmak mümkün duyuyorum

protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
     throws ServletException, IOException { 

    PrintWriter outp = resp.getWriter(); 

    StringBuffer buff = new StringBuffer(); 

    File file1 = (File) req.getAttribute("userfile1"); 
    String p = req.getParameter("path"); 
    boolean success = false; 

    if (file1 == null || !file1.exists()) { 
     buff.append("File does not exist\n"); 
    } else if (file1.isDirectory()) { 
     buff.append("File is a directory\n"); 
    } else { 
     File outputFile = new File(req.getParameter("userfile1")); 
     if(isValidPath(p)){ 
      p = DRIVE_ROOT + p; 
      final File finalDest = new File(p 
        + outputFile.getName()); 
      success = false; 
      try { 
       copyFileUsingFileChannels(file1, finalDest); 
       finalDest.setWritable(true); 
       success = true; 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      if (success){ 
       buff.append("File successfully uploaded.\n"); 
      } 
      else{ 
            buff.append("Failed to save file."); 
      } 
     } 
     else{ 
      buff.append("Invalid path.\n"); 
     } 
    } 
    outp.write(buff.toString()); 
} 

: Pi günü bir servlet çalışan var.

ui-elements.html yüklendi:

@ResponseBody 
@RequestMapping(value="/upload/",method=RequestMethod.POST ,produces = "text/plain") 
public String uploadFile(MultipartHttpServletRequest request2, HttpServletResponse response2){ 

    Iterator<String> itr = request2.getFileNames(); 

    MultipartFile file = request2.getFile(itr.next()); 
    System.out.println(file.getOriginalFilename() +" uploaded!"); 

    System.out.println(file.toString()); 
    MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>(); 
    parts.add("userfile1",file); 
    //reqEntity.addPart("userfile1", file); 
    String path="/public/"; 
    RestTemplate restTemplate = new RestTemplate(); 
    HttpHeaders headers = new HttpHeaders(); 
    headers.setContentType(MediaType.MULTIPART_FORM_DATA); 
    System.out.println("1"); 
    HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<MultiValueMap<String, Object>>(parts, headers); 
    String url = url2+"/pi/GetFileServlet?path="+path; 
    System.out.println("2"); 
/* restTemplate.getMessageConverters().add(new FormHttpMessageConverter()); 
    restTemplate.getMessageConverters().add(
      new MappingJackson2HttpMessageConverter());*/ 
    System.out.println("3"); 
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request,String.class); 
    System.out.println("4"); 
    System.out.println("response : " +response); 
    if(response==null||response.getBody().trim()==""){ 
     return "error"; 
    } 
    return response.getBody(); 
} 

En fazla bu çıkışı!

org.springframework.web.multipart.su[email protected]47e7673e

numarayı 4 görebileceğiniz gibi İstisna yok baskılı edilmez konsolda. ayıklama sırasında bulunan İstisnalar:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)) (through reference chain: org.springframework.web.multipart.support.StandardMultipartFile["inputStream"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)) (through reference chain: org.springframework.web.multipart.support.StandardMultipartFile["inputStream"]) 
+1

Tamam, belki RestClientException bir stacktrace var? Ekleyebilir misiniz? –

+0

Konsolda bir istisna alamıyorum, ancak hata ayıklama sırasında buldum. Yukarıdakileri ekleyeceğim. En düşük 3.1 ve 3.2 için – Maniek

cevap

13

RestTemplate varsayılan MessageConverters hiçbiri MultipartFile dosyası tarafından bulunan InputStream seri bilen çünkü istisna alıyorsanız. RestTemplate ile nesne gönderirken, çoğu durumda POJO'ları göndermek istersiniz. MultipartFile'ın baytlarını MultipartFile yerine MultiValueMap'e ekleyerek bunu düzeltebilirsiniz.

Ayrıca bülten bölümünüzde bir sorun var. ServletRequest en getAttribute yöntemi isteği/form parametreleri ancak attributes set by the servlet context dönmez olarak Mesela

için
File file1 = (File) req.getAttribute("userfile1"); 

daima boş dönmelidir. Aslında senin curl örneğiyle çalıştığına emin misin? here uyarlanmıştır (Ben bir Spring MVC kap içinde çalışan test rağmen)

Servlet:

@RequestMapping("/pi") 
private void doPost(HttpServletRequest request, HttpServletResponse response) 
     throws ServletException, IOException { 

    final String path = request.getParameter("destination"); 
    final Part filePart = request.getPart("file"); 
    final String fileName = request.getParameter("filename"); 

    OutputStream out = null; 
    InputStream fileContent = null; 
    final PrintWriter writer = response.getWriter(); 

    try { 
    out = new FileOutputStream(new File(path + File.separator 
      + fileName)); 
    fileContent = filePart.getInputStream(); 

    int read = 0; 
    final byte[] bytes = new byte[1024]; 

    while ((read = fileContent.read(bytes)) != -1) { 
     out.write(bytes, 0, read); 
    } 
    writer.println("New file " + fileName + " created at " + path); 

    } catch (FileNotFoundException fne) { 
    writer.println("You either did not specify a file to upload or are " 
      + "trying to upload a file to a protected or nonexistent " 
      + "location."); 
    writer.println("<br/> ERROR: " + fne.getMessage()); 

    } finally { 
    if (out != null) { 
     out.close(); 
    } 
    if (fileContent != null) { 
     fileContent.close(); 
    } 
    if (writer != null) { 
     writer.close(); 
    } 
    } 
} 

Yay Burada

bir sunucu uygulaması için bir dosya ileten bir Spring MVC yöntemin bir örneğidir MVC yöntemi:

@ResponseBody 
@RequestMapping(value="/upload/", method=RequestMethod.POST, 
     produces = "text/plain") 
public String uploadFile(MultipartHttpServletRequest request) 
     throws IOException { 

    Iterator<String> itr = request.getFileNames(); 

    MultipartFile file = request.getFile(itr.next()); 
    MultiValueMap<String, Object> parts = 
      new LinkedMultiValueMap<String, Object>(); 
    parts.add("file", new ByteArrayResource(file.getBytes())); 
    parts.add("filename", file.getOriginalFilename()); 

    RestTemplate restTemplate = new RestTemplate(); 
    HttpHeaders headers = new HttpHeaders(); 
    headers.setContentType(MediaType.MULTIPART_FORM_DATA); 

    HttpEntity<MultiValueMap<String, Object>> requestEntity = 
      new HttpEntity<MultiValueMap<String, Object>>(parts, headers); 

    // file upload path on destination server 
    parts.add("destination", "./"); 

    ResponseEntity<String> response = 
      restTemplate.exchange("http://localhost:8080/pi", 
        HttpMethod.POST, requestEntity, String.class); 

    if (response != null && !response.getBody().trim().equals("")) { 
    return response.getBody(); 
    } 

    return "error"; 
} 

Ben başarıyla aşağıdaki kıvrımın servlet'dir MVC yöntemle dosya yükleyebilir bu kullanma:

curl --form [email protected] localhost:8080/upload/ 
+0

, ben de bayt dizileri gönderirken resttemplate hata ile uğraşmak zorunda - http://stackoverflow.com/questions/4118670/sending-multipart-file-as-post-parameters-with- resttemplate-requests – chrismarx

+0

Sonunda beni kurtardın. Evet Spring MVC benim için mükemmel çalışıyor –

3

Tüm dosyayı bir ByteArrayResource numaralı belgede okumak, büyük dosyalarla birlikte bir bellek tüketim sorunu olabilir.

yapabilirsiniz vekil kullanarak bir bahar mvc denetleyicisi bir dosya yükleme bir InputStreamResource:

@RequestMapping(value = "/upload", method = RequestMethod.POST) 
public ResponseEntity<?> uploadImages(@RequestPart("images") final MultipartFile[] files) throws IOException { 
    LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); 
    String response; 
    HttpStatus httpStatus = HttpStatus.CREATED; 

    try { 
     for (MultipartFile file : files) { 
      if (!file.isEmpty()) { 
       map.add("images", new MultipartInputStreamFileResource(file.getInputStream(), file.getOriginalFilename())); 
      } 
     } 

     HttpHeaders headers = new HttpHeaders(); 
     headers.setContentType(MediaType.MULTIPART_FORM_DATA); 

     String url = "http://example.com/upload"; 

     HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers); 
     response = restTemplate.postForObject(url, requestEntity, String.class); 

    } catch (HttpStatusCodeException e) { 
     httpStatus = HttpStatus.valueOf(e.getStatusCode().value()); 
     response = e.getResponseBodyAsString(); 
    } catch (Exception e) { 
     httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; 
     response = e.getMessage(); 
    } 

    return new ResponseEntity<>(response, httpStatus); 
} 

class MultipartInputStreamFileResource extends InputStreamResource { 

    private final String filename; 

    MultipartInputStreamFileResource(InputStream inputStream, String filename) { 
     super(inputStream); 
     this.filename = filename; 
    } 

    @Override 
    public String getFilename() { 
     return this.filename; 
    } 

    @Override 
    public long contentLength() throws IOException { 
     return -1; // we do not want to generally read the whole stream into memory ... 
    } 
} 
+1

Şaşırtıcı bir şekilde, kabul edilen cevap benim için çalışmadı, ama bu işe yaradı! Teşekkürler. –

+0

@ lorenzo-polidori Lütfen MultipartInputStreamFileResource ürününü nasıl alacağınıza dair örnek denetleyici yöntemi sunabilir misiniz? diğer bir deyişle, InputStreamResource için örnek denetleyici yöntemi – Krish

İlgili konular