Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading file on server using retrofit

In my project, I've got to send an image taken from android device to server site, where it should be stored on disk. Unfortunately, when I call the method on the device site I meet this error:

DEBUG/Retrofit(4429): java.lang.RuntimeException: 
    Unable to write multipart request.
at retrofit.mime.MultipartTypedOutput.buildPart(MultipartTypedOutput.java:86)
at retrofit.mime.MultipartTypedOutput.addPart(MultipartTypedOutput.java:49)
at retrofit.RequestBuilder.setArguments(RequestBuilder.java:211)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:264)
at retrofit.RestAdapter$RestHandler.access$500(RestAdapter.java:197)
at retrofit.RestAdapter$RestHandler$1.obtainResponse(RestAdapter.java:243)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:38)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at retrofit.Platform$Android$2$1.run(Platform.java:134)
at java.lang.Thread.run(Thread.java:856)

Caused by: java.io.FileNotFoundException: /external/images/media/1270: 
    open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:416)
at java.io.FileInputStream.<init>(FileInputStream.java:78)
at retrofit.mime.TypedFile.writeTo(TypedFile.java:74)
at retrofit.mime.MultipartTypedOutput.buildPart(MultipartTypedOutput.java:83)
... 10 more

Caused by: libcore.io.ErrnoException: 
    open failed: ENOENT (No such file or directory)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
at libcore.io.IoBridge.open(IoBridge.java:400)
... 13 more

That's the method's declaration

@Multipart
@POST("/monument/photo/upload")
void addMonumentPhoto(@Part("MonumentID") int monumentId,
                      @Part("name") String name,
                      @Part("subscript") String subscript,
                      @Part("photo") TypedFile photo,
                      Callback<Photo> callback);

... and that's how I call it

photo = new File(selectedImageUri.getPath());
typedFile = new TypedFile("application/octet-stream", photo);
MonumentsUtil.getApi().addMonumentPhoto(monument.getIdZabytek(),
      "podpis",
      "Main photo",
      typedFile,
      new Callback<Photo>() {
    @Override
    public void success(Photo aPhoto, Response response) {
    }

    @Override
    public void failure(RetrofitError retrofitError) {
         Log.e(TAG, retrofitError.getMessage());
    }
});

On the server's site I've got such methods:

@RequestMapping(value="/monument/photo/upload", method=RequestMethod.POST)
public @ResponseBody Photo requestMonumentPhotoAdd(
       @RequestParam("MonumentID") int monumentId,
       @RequestParam("name") String name ,
       @RequestParam("subscript") String subscript,
       @RequestParam("photo") org.springframework.web.multipart.MultipartFile file) {

    Photo photo = new Photo();
    photo.setIdZabytek(monumentId);
    photo.setUri(URL+ "/images/" + name);
    photo.setPodpis(subscript);
    photo = monumentsRepo.addPhoto(photo);
    String filePath = "D:\\Projekty\\Images\\" + monumentId + ":" + photo.getIdZjecia();

    if (!file.isEmpty()) {
        try {
            byte[] bytes = file.getBytes();
            BufferedOutputStream stream = new BufferedOutputStream(
                new FileOutputStream(new File(filePath)));
            stream.write(bytes);
            stream.close();
            photo.setUri(filePath);
            monumentsRepo.updatePhoto(photo);
            return photo;
        } catch (Exception e) {
            return null;
        }
    } else {
        return null;
    }
}

The program get to the failure block and I don't know why. Can anybody point the mistake and explain what's wrong?

EDIT

After correction in my code I've got next error which I can't fix:

java.net.ProtocolException: content-length promised 1431984 bytes, but received 0      
    com.squareup.okhttp.internal.http.RetryableOutputStream.close(RetryableOutputStream.java:52),
    com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:629),
    com.squareup.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java: 346),
    com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:295),
    com.squareup.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:489), 
retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90), 
retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48), 
retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287), 
retrofit.RestAdapter$RestHandler.access$500(RestAdapter.java:197), 
retrofit.RestAdapter$RestHandler$1.obtainResponse(RestAdapter.java:243), 
retrofit.CallbackRunnable.run(CallbackRunnable.java:38), 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076), 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569), 
retrofit.Platform$Android$2$1.run(Platform.java:134), 
java.lang.Thread.run(Thread.java:856)

and the HTTP Response

HTTP/1.1 400 Bad Request, 
Connection: close, 
Content-Length: 1068, 
Content-Type:     text/html;charset=utf-8, 
Date: Wed, 11 Dec 2013 16:45:39 GMT,  
OkHttp-Received-Millis: 1386780339873, 
OkHttp-Response-Source: NETWORK 400,
OkHttp-Selected-Transport: http/1.1, 
OkHttp-Sent-Millis: 1386780339799, Server: Apache-Coyote/1.1

I think that the server's method could be wrongly written but I'm not sure. Could anybody help with it?

like image 930
Tiny dragons tail Avatar asked Dec 10 '13 22:12

Tiny dragons tail


People also ask

How do I upload a file to a server?

Right-click the folder and select “Upload other file here. . .“. Browse the server for the file you want to upload. Select the file and click Open. Now, you will see the file in the folder location on the server.


1 Answers

Uri#getPath returns the path component of the Uri, not the path on the filesystem.

You need to query the content provider for the actual image. Something like this: https://stackoverflow.com/a/20186918/132047

like image 96
Jake Wharton Avatar answered Sep 19 '22 19:09

Jake Wharton