I am sending a photo to the server Shipping Code:

Call<String> call = service.uploadFile(descriptionString, body); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { path[0] = response.body(); Log.e("samuliak", "Succesful:"+response.body()); } @Override public void onFailure(Call<String> call, Throwable t) { Log.e("samuliak", "Upload error:"+t.toString()); } }); 

Here is the retrofit API:

 @Multipart @POST("psychologist/upload") Call<String> uploadFile(@Part("name") String description, @Part MultipartBody.Part file); 

But the controller method:

 @RequestMapping(value="/psychologist/upload", method=RequestMethod.POST) @ResponseBody public String uploadFile(@RequestParam("name") String name, @RequestParam("file") MultipartFile file){ if (!file.isEmpty()) { String path = ""; try { byte[] bytes = file.getBytes(); path = new File(name + "-uploaded").getPath(); System.out.println(path); BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(name + "-uploaded"))); stream.write(bytes); stream.close(); return path; } catch (Exception e) { System.out.println("Вам не удалось загрузить " + name + " => " + e.getMessage()); return "Вам не удалось загрузить " + name + " => " + e.getMessage(); } } else { return "Вам не удалось загрузить " + name + " потому что файл пустой."; } } 

I understand that the method is incorrectly formed, so please explain to me how to properly! I really want to know this, it's very difficult to figure it out myself and I have been sitting and suffering for 4 hours already! Help!

UPDATE

  08-04 13:55:02.670 24439-24439/com.project.samuliak.psychogram E/samuliak: Activity result in Registr.. 08-04 13:55:02.692 24439-24439/com.project.samuliak.psychogram E/samuliak: path from act.result > /storage/emulated/0/DCIM/Camera/IMG_20160624_141505_1.jpg 08-04 13:55:02.705 24439-24454/com.project.samuliak.psychogram I/art: Background partial concurrent mark sweep GC freed 482(34KB) AllocSpace objects, 1(16KB) LOS objects, 39% free, 3MB/6MB, paused 6.386ms total 15.981ms 08-04 13:55:02.711 24439-24451/com.project.samuliak.psychogram W/CursorWrapperInner: Cursor finalized without prior close() 08-04 13:55:02.779 24439-24439/com.project.samuliak.psychogram E/samuliak: uploadFile. End. 08-04 13:55:02.808 24439-24478/com.project.samuliak.psychogram W/EGL_emulation: eglSurfaceAttrib not implemented 08-04 13:55:02.808 24439-24478/com.project.samuliak.psychogram W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe2026ee0, error=EGL_SUCCESS 08-04 13:55:03.045 24439-24439/com.project.samuliak.psychogram E/samuliak: not succesful > Bad Request 08-04 13:55:03.045 24439-24439/com.project.samuliak.psychogram E/samuliak: body > :null 

UPDATE Update Cataline Log

 05-Aug-2016 10:42:31.506 INFO [RMI TCP Connection(3)-127.0.0.1] org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl.useContextualLobCreation HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException 
  • What exactly is your question? How do you understand that the method does not work correctly? - Nofate
  • When sending a file to the server, the callback throws in "onFailure" - Samuliak
  • one
    Well, what does t.toString () print? Or a full report - t.printStackTrace () that will output? - mit
  • java.io.EOFException: End of input at line 1 column 1 shows what it’s - Samuliak

1 answer 1

The problem is that Retrofit expects JSON from the server, and you return a string.

 @ResponseBody public String uploadFile(...) { ... } 

Create a wrapper class for the string:

 public class StringResponse { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } } 

Use it to return a string in the controller.

 @RequestMapping(value="/psychologist/upload", method=RequestMethod.POST) @ResponseBody public StringResponse uploadFile(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) { // ... ваш код ... StringResponse resp = new StringResponse(); resp.setValue(path); return resp; // ... ваш код ... } 

and retrofit interface

 @Multipart @POST("psychologist/upload") Call<StringResponse> uploadFile(@Part("name") String description, @Part MultipartBody.Part file); 

When it works, take care of error handling. Add to the StringResponse field error , in which you will put the error text. value in this case can be set to null . Or else add a field with a flag of unsuccessful completion. boolean failed .

After that, you may want to generalize the class for any results returned by the server. You should also think about getting rid of setters, making all the fields final and adding convenient factory methods.

 public class ServerResponse<T> { private final T value; private final boolean failed; private final String errorMsg; public T getValue() { return value; } public boolean isFailed() { return failed; } public String getErrorMsg() { return errorMsg; } public static ServerResponse<T> ok(T value) { ServerResponse<T> resp = new ServerResponse<>(); resp.value = value; return resp; } public static ServerResponse<T> error(String errorMsg) { ServerResponse<T> resp = new ServerResponse<>(); resp.errorMsg = errorMsg; resp.failed = true; return resp; } } 

So you get a universal wrapper class in which you can add service fields (error codes, pagination, timestamps) as needed, without affecting the main content in the value field.

  // ... ваш код ... return StringResponse.ok(path); // ... ваш код ... return StringResponse.error("Вам не удалось загрузить " + name + " потому что файл пустой."); 
  • Unfortunately, it does not work (it turns out the error "Bad Request" - Samuliak
  • I can’t help without a tool - Nofate
  • added to first post - Samuliak
  • I meant server infrastructure - Nofate
  • for some reason there are no traces (using System.out.println () does not output anything, even in other methods. What could be the problem? The only thing is, this is a line from Tomcat Cataline Log (added to the main post) - Samuliak