Retrofit 2 Working In Postman and Localhost but Not On Amazon AWS Live Server

My retrofit instance is working fine with localhost (both android code and postman), and working fine online with postman. But when I go to Amazon AWS instance (a.k.a online) the android part is not working. Please see my code below. The error log from android is D/response: {"error":true,"message":"Required parameters are not available"}

Interestingly the problem is with large file sizes 2M, small file sizes 24KB are getting uploaded fine. I have already checked the php.ini file the max sizes there are 25MB

I am following this tutorial : https://www.simplifiedcoding.net/retrofit-upload-file-tutorial/

public interface Api {

    //the base URL for our API
    //make sure you are not using localhost
    //find the ip usinc ipconfig command
    String BASE_URL = "http://creative-thinker.com/files/images/secret_crushes/";

    //this is our multipart request
    //we have two parameters on is name and other one is description
    @Multipart
    @POST("Api.php?apicall=upload")
    Call<MyResponse> uploadImage(@Part("image\"; filename=\"myfile.jpg\" ")
                                         RequestBody file, @Part("desc") RequestBody desc);

}

My Object Class

public class MyResponse {
    public boolean error;
    String message;
}

My Fragment

ivImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        // Open The File Choose And Send To Activity For Result
        Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(i, 100);

    }
});

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100 && data != null) {
            //the image URI
            Uri selectedImage = data.getData();

            //calling the upload file method after choosing the file
            uploadFile(selectedImage, "My Image");
        }
    }

    private void uploadFile(Uri fileUri, String desc) {

        //creating a file
        File file = new File(getRealPathFromURI(fileUri));

        //creating request body for file
        RequestBody requestFile = RequestBody.create(MediaType.parse(getContext().getContentResolver().getType(fileUri)), file);
        RequestBody descBody = RequestBody.create(MediaType.parse("text/plain"), desc);

        //The gson builder
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        //creating retrofit object
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Api.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();


        //creating our api
        Api api = retrofit.create(Api.class);

        //creating a call and calling the upload image method
        Call<MyResponse> call = api.uploadImage(requestFile, descBody);

        //finally performing the call
        call.enqueue(new Callback<MyResponse>() {
            @Override
            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
                if (!response.body().error) {
                    Toast.makeText(getContext().getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
                } else {

                    MyResponse res= response.body();
                    Log.d("response", new Gson().toJson(res));
                    Toast.makeText(getContext().getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<MyResponse> call, Throwable t) {
                Toast.makeText(getContext().getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }

    /*
     * This method is fetching the absolute path of the image file
     * if you want to upload other kind of files like .pdf, .docx
     * you need to make changes on this method only
     * Rest part will be the same
     * */
    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new CursorLoader(getContext(), contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }

FileHandler.php

<?php


class FileHandler
{

    private $con;

    public function __construct()
    {
        require_once dirname(__FILE__) . '/DbConnect.php';

        $db = new DbConnect();
        $this->con = $db->connect();
    }

    public function saveFile($file, $extension, $desc)
    {
        $name = round(microtime(true) * 1000) . '.' . $extension;
        $filedest = dirname(__FILE__) . UPLOAD_PATH . $name;
        move_uploaded_file($file, $filedest);

        $url = $server_ip = gethostbyname(gethostname());

        $stmt = $this->con->prepare("INSERT INTO images (description, image) VALUES (?, ?)");
        $stmt->bind_param("ss", $desc, $name);
        if ($stmt->execute()) {
            return true;
        }

        return false;
    }

    public function getAllFiles()
    {
        $stmt = $this->con->prepare("SELECT id, description, image FROM images ORDER BY id DESC");
        $stmt->execute();
        $stmt->bind_result($id, $desc, $url);

        $images = array();

        while ($stmt->fetch()) {

            $temp = array();
            $absurl = 'http://' . gethostbyname(gethostname()) . '/files/images/secret_crushes' . UPLOAD_PATH . $url;
            $temp['id'] = $id;
            $temp['desc'] = $desc;
            $temp['url'] = $absurl;
            array_push($images, $temp);
        }

        return $images;
    }

}

Api.php

<?php


require_once dirname(__FILE__) . '/FileHandler.php';

$response = array();

if (isset($_GET['apicall'])) {
    switch ($_GET['apicall']) {
        case 'upload':

            if (isset($_POST['desc']) && strlen($_POST['desc']) > 0 && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
                $upload = new FileHandler();

                $file = $_FILES['image']['tmp_name'];

                $desc = $_POST['desc'];

                if ($upload->saveFile($file, getFileExtension($_FILES['image']['name']), $desc)) {
                    $response['error'] = false;
                    $response['message'] = 'File Uploaded Successfullly';
                }

            } else {
                $response['error'] = true;
                $response['message'] = 'Required parameters are not available';
            }

            break;

        case 'getallimages':

            $upload = new FileHandler();
            $response['error'] = false;
            $response['images'] = $upload->getAllFiles();

            break;
    }
}

echo json_encode($response);

function getFileExtension($file)
{
    $path_parts = pathinfo($file);
    return $path_parts['extension'];
}

I am trying to catch the values of items in Api.php using

$response['message'] = $string; just where $response['message'] = 'Required parameters are not available';

and getting the following results

    $string = $_POST['desc'];
    D/response: {"error":true,"message":"My Image"}

    $string = $_POST['desc'];
    $string = strlen($string);
    D/response: {"error":true,"message":"8"}

    $string = $_FILES['image']['error'];
    D/response: {"error":true}

    $string = UPLOAD_ERR_OK;
    D/response: {"error":true,"message":"0"}

And removing && $_FILES['image']['error'] === UPLOAD_ERR_OK enters the data into database but no image still uploaded

Answers 1

  • Finally found the solution after searching the net... The issue was file size

    I am on php 7 and Apache. So the configuration needs to changed at two places

    The configuration

    upload_max_filesize = 25M
    post_max_size = 25M
    max_execution_time = 300
    max_input_time = 300
    memory_limit = 128M
    

    The locations

    sudo nano /etc/php/7.0/fpm/php.ini
    sudo nano /etc/php/7.0/apache2/php.ini
    

    Apparently the settings needs to be changed for PHP AND Apache on Amazon AWS. Hope it helps others.


Related Articles