No such file or diectory error in image file upload using Retrofit in Android
<p>I am developing an Android app. In my app, I am using Retrofit to upload image and pdf files to server in multipart/form-data request. I am new to Retrofit. </p>

<p>I uploaded pdf file and other string data successfully. But when I upload Image file, it is giving me "No such file or directory" exception even I did the same thing as PDF file that is successfully uploaded.</p>

<p>This is my activity upload pdf file and image file</p>

<pre><code>public class ContributeActivity extends AppCompatActivity {

    public static final int SELECT_PICTURE = 2334;
    public static final int SELECT_BOOK  = 123;

    //other properties
    private File bookFile;
    private File imageFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        app = (AppSingleton)getApplication();
        app.initialize();
        setContentView(R.layout.activity_contribute);
        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        //do other steps
    }

    private void saveBtnClick()
    {
        contributeBook();
    }

    private void openImagePicker()
    {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
    }

    private void setUpFilePickerImage()
    {
        ivBookFile.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openBookFilePicker();
            }
        });
    }

    private void openBookFilePicker()
    {
        Intent intent = new Intent();
        intent.setType("*/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select file"), SELECT_BOOK);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                if(selectedImageUri!=null)
                {
                    try{
                        bmpCoverImage = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImageUri);
                        imageFile = new File(selectedImageUri.getPath());
                        if(bmpCoverImage!=null)
                        {
                            ivCoverImage.setImageBitmap(bmpCoverImage);
                        }
                    }
                    catch (IOException e)
                    {
                        Toast.makeText(getBaseContext(),"An error occurred with the file selected",Toast.LENGTH_SHORT).show();
                    }
                }
            }
            else if(requestCode==SELECT_BOOK)
            {
                Uri bookUri = data.getData();
                if(bookUri!=null)
                {
                    String filePath = bookUri.toString();//bookUri.toString()
                    String mime = app.getMimeType(filePath);
                    if(mime!=null &amp;&amp; !mime.isEmpty() &amp;&amp; (mime.toLowerCase()=="application/pdf" || mime.toLowerCase()=="application/txt" || mime.toLowerCase()=="application/text"))
                    {
                        bookFile = new File(bookUri.getPath());
                        ivBookFile.setImageResource(R.drawable.book_selected);
                    }
                    else{
                        Toast.makeText(getBaseContext(),"Unable to process file you have chosen.",Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    }

    private Boolean validateForm()
    {

        // do validation
        return true;
    }

    private void contributeBook()
    {
        RetrofitService service = RetrofitClient.retrofit.create(RetrofitService.class);
        MultipartBody.Part bodyBookFile = null;
        if(bookFile!=null)
        {
            RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), bookFile);
            bodyBookFile = MultipartBody.Part.createFormData("book_file", bookFile.getName(), requestFile);
        }

        MultipartBody.Part bodyImageFile = null;
        if(imageFile!=null)
        {
            RequestBody requestImageFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile);
            bodyImageFile = MultipartBody.Part.createFormData("image_file",imageFile.getName(),requestImageFile);
        }

        RequestBody title = RequestBody.create(MediaType.parse("multipart/form-data"), tfTitle.getText().toString());
        RequestBody mmTitle = RequestBody.create(MediaType.parse("multipart/form-data"), tfMmTitle.getText().toString());
        RequestBody parentId = RequestBody.create(MediaType.parse("multipart/form-data"),String.valueOf(selectedParentId));
        RequestBody childId = RequestBody.create(MediaType.parse("multipart/form-data"), String.valueOf(selectedChildId));
        RequestBody authorName = RequestBody.create(MediaType.parse("multipart/form-data"), tfAuthorName.getText().toString());
        RequestBody authorMmName = RequestBody.create(MediaType.parse("multipart/form-data"), tfAuthorMmName.getText().toString());
        RequestBody authToken = RequestBody.create(MediaType.parse("multipart/form-data"),app.getAuthToken());

        Call&lt;ResponseBody&gt; call = service.contributeBook(bodyImageFile,bodyBookFile,title,mmTitle,parentId,childId,authorName,authorMmName,authToken);
        call.enqueue(new Callback&lt;ResponseBody&gt;() {
            @Override
            public void onResponse(Call&lt;ResponseBody&gt; call, Response&lt;ResponseBody&gt; response) {
                if(response!=null &amp;&amp; response.isSuccessful())
                {
                    Toast.makeText(getBaseContext(),"Book successfully contributed. Thank you.",Toast.LENGTH_SHORT).show();
                }
                else if(response!=null &amp;&amp; !response.isSuccessful() &amp;&amp; response.errorBody()!=null)
                {
                    //server error
                    Toast.makeText(getBaseContext(),"Validation errors",Toast.LENGTH_SHORT).show();
                }
                else{
                    Toast.makeText(getBaseContext(),"An error occurred in server",Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call&lt;ResponseBody&gt; call, Throwable t) {
                Toast.makeText(getBaseContext(),t.getMessage(),Toast.LENGTH_SHORT).show();
            }
        });
    }
}
</code></pre>

<p>This is my retrofit service interface</p>

<pre><code>public interface RetrofitService {
    @Multipart
    @POST("book/contribute")
    Call&lt;ResponseBody&gt; contributeBook(@Part MultipartBody.Part imageFile,@Part MultipartBody.Part bookFile,@Part("title") RequestBody title
    ,@Part("mm_title") RequestBody mmTitle,@Part("parent_category_id") RequestBody parentId,@Part("child_category_id") RequestBody childId
    ,@Part("author_name") RequestBody authorName,@Part("author_mm_name") RequestBody authorMmName,@Part("auth_token") RequestBody authToken);
}
</code></pre>

<p>This is my retrofit client class</p>

<pre><code>public class RetrofitClient {
    //implementation starts - should be in different class
    public static final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(LinkConfig.API_END_POINT)
            .client(RetrofitClient.httpClient())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    public static OkHttpClient httpClient()
    {
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request original = chain.request();

                Request request = original.newBuilder()
                        .header(AppSingleton.API_KEY_FIELD, AppSingleton.API_KEY)
                        .method(original.method(), original.body())
                        .build();

                return chain.proceed(request);
            }
        });
        return httpClient.build();
    }
}
</code></pre>

<p>With the above code, I send pdf file with other string fields but without image file field. Everything worked fine. PDF file successfully uploaded to server and data are saved in the database. But when I chose the image file and submit data to server, it gives me following error in error listener of retrofit.</p>

<p><a href="https://i.stack.imgur.com/blzWj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/blzWj.png" alt="enter image description here"></a></p>

<p>I got that error before when I first upload pdf file. I have to change as in activity result after choosing file.</p>

<p>From</p>

<pre><code>uri.toString()
</code></pre>

<p>To</p>

<pre><code>uri.getPath()
</code></pre>

<p>But as you can see, I did the same thing to both PDF file and Image file in activity result. But PDF file is working well and image file is giving me error.</p>

<p>These are permissions set in manifest file</p>

<pre><code>&lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
    &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
    &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
</code></pre>