4

I'm testing some way to do a send an image using Retrofit library. In documentations of Retrofit here: http://square.github.io/retrofit/ there's a way using @MultiPart annotation. I'm trying use like a documentation but still doesn't work to me.

How can I do it ?

Here how I'm trying.

Web Service php file

if($_REQUEST["uploadfile"] == "add"){
    $uploaddir = 'C:\Users\fernando\Pictures';
    $uploadfile = $uploaddir . $_FILES['userfile']['name'];

    $response = array();
    //param
    $response["nome"] = $_REQUEST["nome"];


    if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) {
        $response["msg"] = "O arquivo é valido e foi carregado com sucesso. Aqui esta alguma informação:\n";
        print_r($_FILES);
    }  else {
        $response["msg"] = "Possivel ataque de upload! Aqui esta alguma informação:\n";
        print_r($_FILES);
    }
    $json = json_encode($response);
    echo $json;
}

Listener to Usuario

public interface UsuarioListener {

    //send an image with params with Post
    @Multipart
    @POST("/android/login.php")
    void setUserImage(
            @QueryMap Map<String, String> params,
            @Part("pathImage") TypedFile file,          
            Callback<JsonElement> response);

}

Activity

btnEnviar.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                setUserImage();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RESULT_LOAD_IMAGE && 
            resultCode == RESULT_OK && 
            null != data) {
            Uri selectedImage = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };

            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            pathImage = cursor.getString(columnIndex);
            cursor.close();
        }
    }

    public void setUserImage() {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("nome", "Fernando Paiva Campos");

        RestAdapter adapter = new RestAdapter.Builder()
                            .setLogLevel(RestAdapter.LogLevel.FULL)
                            .setEndpoint(END_POINT).build();
        UsuarioListener listener = adapter.create(UsuarioListener.class);

        TypedFile image = new TypedFile("image/jpg", new File(pathImage));
        listener.setUserImage(
                              params,
                              image,
                              new Callback<JsonElement>() {
            @Override
            public void success(JsonElement arg0, Response arg1) {
                Log.i("JSON_ELEMENT:", arg0.toString() + "");
            }

            @Override
            public void failure(RetrofitError arg0) {
                Log.e("ERROR:", arg0.getLocalizedMessage());

            }
        });     
    }

Exception

E/ERROR:(5200): com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 6

JJD
  • 50,076
  • 60
  • 203
  • 339
FernandoPaiva
  • 4,410
  • 13
  • 59
  • 118
  • If there is only 1 part (the file) you don't need to use multipart. – Philio Nov 30 '14 at 02:24
  • Without `@MultiPart` annotation throws this exception: `11-30 00:38:44.105: E/ERROR:(7097): UsuarioListener.setUserImage: @Part parameters can only be used with multipart encoding. (parameter #2) ` – FernandoPaiva Nov 30 '14 at 02:39
  • You'd have to use @Body for the image instead. – Philio Dec 01 '14 at 07:21

2 Answers2

1

It looks like the error referenced above is related to your php output. It is unclear whether the upload succeeded or not, but your response is invalid JSON because before you echo the JSON response, you also print out the value of $_FILES. Try commenting out the lines with the following code in your php file.

print_r($_FILES);
iagreen
  • 31,470
  • 8
  • 76
  • 90
0

There are two corrections in your problems:

In your this code:

public interface UsuarioListener {

    //send an image with params with Post
    @Multipart
    @POST("/android/login.php")
    void setUserImage(
        @QueryMap Map<String, String> params,
        // the @Part has the parameter "pathImage". 
        // You should pass this in your php code.
        @Part("pathImage") TypedFile file, 
        Callback<JsonElement> response);
}

So your php code should like as:

if($_REQUEST["uploadfile"] == "add"){
$uploaddir = 'C:\Users\fernando\Pictures';
$uploadfile = $uploaddir . $_FILES['userfile']['name'];

$response = array();
//param
$response["nome"] = $_REQUEST["nome"];

if (move_uploaded_file($_FILES['pathImage']['tmp_name'], $uploaddir . $_FILES['pathImage']['name']))

The final correction in your Retrofit client:

TypedFile typedImage = new TypedFile("application/octet-stream", photo);

For details you can have a loon into my answer for similar problem: Retrofit Multipart Upload Image failed

Community
  • 1
  • 1
techhunter
  • 300
  • 5
  • 18