简体   繁体   中英

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM