2016-08-18 10 views
0

Ich benutze Spring 4 neuesten, und ich habe generell kein Problem, RESTful-Controller zu schreiben. Es gibt eine Legacy-Web-App, die java.net.HTTPUrlConnection verwendet, um einen mehrteiligen Upload durchzuführen. Es gibt 3 Daten, die wir hochladen: 1 ist eine PDF-Datei, und wir haben die Bytes, dann sind die anderen zwei Daten nur 2 Zeichenfelder.Spring MVC File Upload mit mehrteiligen Daten und Unit-Test

Zunächst lassen Sie mich Ihnen den Frühling REST-Controller die Daten zu akzeptieren:

@RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data") 
public @ResponseBody boolean saveData(@RequestPart(value = "field1") String field1, @RequestPart(value = "field2") String field2, @RequestParam(value = "pdfbytes") String pdfbytes) 
{ 
    System.out.println("saveData: field1=" + field1); 
    System.out.println("saveData: field2=" + field2); 
    System.out.println("saveData: pdfbytes=" + pdfbytes); 
    boolean response = true; 

    return response; 
} 

Der Code in Front-End, für die das Senden von Daten unter Verwendung von 'java.net.HttpURLConnection' wie folgt aussieht:

String boundary = MultiPartFormOutputStream.createBoundary(); 

URL uploadDocumentUrl = new URL(protocol + "://" + host + UPLOAD_EDITED_DOCUMENT); 

    HttpURLConnection urlConn = (HttpURLConnection) MultiPartFormOutputStream.createConnection(uploadDocumentUrl); 
    urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary)); 
    urlConn.setRequestProperty("Connection", "Keep-Alive"); 
    urlConn.setRequestProperty("Cache-Control", "no-cache"); 
    urlConn.setRequestProperty("User-Agent", userAgent); 
    urlConn.setRequestMethod("POST"); 

    MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary); 

    String pdfbytes= getEncodedDocument(pdf); 

    out.writeField("field1", field1); 
    out.writeField("field2", field2); 
    out.writeField("pdfbytes", pdfbytes); 

    out.close(); 
    int responseCode = urlConn.getResponseCode(); 
    String responseMessage = urlConn.getResponseMessage(); 

„MultiPartFormOutputStream“ ist ein benutzerdefiniertes Objekt, das über Daten senden HttpURLConnection erstellt wurde, ist es ziemlich Standard-Code. Ich vertraue ihr zu dieser Zeit.

Also, basierend auf wie wir die Daten senden, muss ich den Controller ändern, um etwas anderes zu tun, oder sieht das in Ordnung?

Hier ist der Code, dass ich Einheit Test bin mit diesen Controller:

@Test 
public void testMockUpload() throws Exception 
{ 
    // Load resource being uploaded 
    byte[] pdfbytes = getByteArrayFromFile(FILENAME); 

    MockMultipartFile firstFile = new MockMultipartFile("field1", "", "text/plain", "field1 data".getBytes()); 
    MockMultipartFile secondFile = new MockMultipartFile("field2", "", "text/plain", "field2 data".getBytes()); 
    MockMultipartFile jsonFile = new MockMultipartFile("pdfbytes", "", "text/plain", pdfbytes); 

    MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.fileUpload(BASE_URL + "/save").file(firstFile).file(secondFile).file(jsonFile) 
    .with(user(USERNAME).roles("role1", "role2")).contentType(MediaType.MULTIPART_FORM_DATA_VALUE); 

    this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk()); 
} 

Und die Fehler, die ich jetzt zurück zu bekommen, ist: org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException

die ich untersuche. Wenn ich Änderungen an der Erstellung meines Tests vornehmen muss, bin ich sehr offen dafür. Irgendwann werde ich alles bekommen, um zwischen dem sendenden Code, dem empfangenden Controller und dem Komponententest zu synchronisieren.

Vielen Dank im Voraus! Wie üblich, wenn es andere Daten oder Informationen gibt, die ich zur Verfügung stellen kann, lassen Sie es mich wissen. Vielen Dank!

Antwort

0

Um eine Datei hochzuladen, würden Sie den Typ RequestParam als org.springframework.web.multipart.MultipartFile;

@RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data") 
      public @ResponseBody boolean saveData(@RequestParam(value = "file") MultipartFile file) 
      { 
       return response; 
      } 

für mehrere Dateien, die ich würde versuchen, eine Wrapper Form zu erstellen:

public class UploadForm{ 

    private List<MultipartFile> files; 
} 

Binden an diese in der Steuerung:

@RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data") 
    public @ResponseBody boolean saveData(@ModelAttribute uploadForm) 
    { 
     return response; 
    } 

und dann Spring Unterstützung für indizierte Felder verwenden zu binden zu einer Sammlung:

Test:

MockMultipartFile firstFile = new MockMultipartFile("files[0]", "", "text/plain", "field1 data".getBytes()); 
    MockMultipartFile secondFile = new MockMultipartFile("files[1]", "", "text/plain", "field2 data".getBytes()); 
    MockMultipartFile jsonFile = new MockMultipartFile("files[2]", "", "text/plain", pdfbytes); 

Auftraggeber:

out.writeField("files[0]", file1Bytes); 
out.writeField("files[1]", file2Bytes); 
...