1

I am working with the Google Drive for the first time. I am trying to upload a jpg file to my Google Drive through my app. I have completed the OAuth 2.0 authorization for account login and drive permission. I have successfully uploaded the file to Google Drive also following the instructions given here https://developers.google.com/drive/api/v3/manage-uploads?refresh=1

The issue is with the uploaded file. The image is not saved there as an image. What should be the form of the request body here?

Here is the code snippet I have used to upload the image file using Google REST API.

OkHttpClient client = new OkHttpClient();
            RequestBody body = RequestBody.create(MediaType.parse("application/json"), file);
            Request request = new Request.Builder()
                    .url("https://www.googleapis.com/upload/drive/v3/files?uploadType=media")
                    .addHeader("Content-Type", "image/jpeg")
                    .addHeader("Content-Length", "36966.4")
                    .addHeader("Authorization", String.format("Bearer %s", accessToken))
                    .post(body)
                    .build();
            Response response = null;
            try {
                response = client.newCall(request).execute();
                successCode = String.valueOf(response.code());
            }catch (IOException e){
                e.printStackTrace();
            }

Here "file" is the Base64 encoded string of the image.

Its just giving the expected http ok 200 code. Also need to know how to set the title for the file while uploading on Google Drive.

3 Answers 3

1

You have mentioned wrong content type in the request. It should be

RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file);
Sign up to request clarification or add additional context in comments.

1 Comment

Hi Coder, thanks for your prompt answer. I would like to inform that I have tried with your solution also but I got 401 i.e. Bad Request every time. I am sharing the playground link here developers.google.com/oauthplayground Please play with that link. It might help you a lot.
1

(Posted on behalf of the question author).

Here is the answer to all my questions. The questions were

  1. Create a folder on the Google drive with a desired name.
  2. Upload a file (image/audio/video) to that particular folder.

Let's start with the point #1. Here is the working code to create a folder on the Google drive with a desired name. I would like to mention one more thing that is related to OAuth 2.0 authorization. As per Google guidance I have used the code from Codelab. Here is the link to get the code https://codelabs.developers.google.com/codelabs/appauth-android-codelab/?refresh=1#0 The scope should be the API provided by the Google for that particular service. For me it is "https://www.googleapis.com/auth/drive.file".

String metaDataFile = "{\"name\": \"folderName\","+ "\"mimeType\": \"application/vnd.google-apps.folder\"}";
            RequestBody requestBodyMetaData = RequestBody.create(MediaType.parse("application/json; charset=UTF-8"), metaDataFile);
            Request request = new Request.Builder()
                    .url("https://www.googleapis.com/drive/v3/files?")
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", String.format("Bearer %s", accessToken))
                    .post(requestBodyMetaData)
                    .build();
            Response response = null;
            OkHttpClient client = new OkHttpClient();
            try {
                response = client.newCall(request).execute();
                successCode = String.valueOf(response.code());
            }catch (IOException e){
                e.printStackTrace();
            }

Now you have to get the folder id. Here is the code to get the folder id.

Request request = new Request.Builder()
                    .url("https://www.googleapis.com/drive/v3/files")
                    .addHeader("Authorization", String.format("Bearer %s", accessToken))
                    .addHeader("Accept", "application/json")
                    .build();
            Response response = null;
            OkHttpClient client = new OkHttpClient();
            try {
                response = client.newCall(request).execute();
                String jsonFile = response.body().string();
                JSONObject jsonObject = new JSONObject(jsonFile);
                JSONArray jsonArray = jsonObject.getJSONArray("files");
                for (int i=0; i<jsonArray.length(); i++){
                    JSONObject json = jsonArray.getJSONObject(i);
                    String fileName = json.getString("name");
                    if (fileName.equalsIgnoreCase("folderName")) {
                        folderId = json.getString("id");
                        if (!folderId.equalsIgnoreCase(""))
                            preferences.setFolderCreated(true, folderId);
                        break;
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
            catch (JSONException e){
                e.printStackTrace();
            }
            catch (NullPointerException e){
                e.printStackTrace();
            }

This folder id is needed to identify the folder where we are going to upload the file. Select the file from your list and then pass that file in the byte[] format to this code. Here we have to use mediatype as multipart because if we use simple upload (media) we cannot set a desired name to the uploaded file.

String metaDataFile = "{\"name\":\"uploadFileName\"," + "\"parents\" : [\""+ pref.getFolderId()+"\"]}"; // json type metadata

                //attaching metadata to our request object
                RequestBody requestBodyMetaData = RequestBody
                        .create(MediaType.parse("application/json; charset=UTF-8"), metaDataFile);
                RequestBody body = RequestBody.create(MediaType.parse("audio/mp4"), file);
                String size = String.valueOf(file.length);

                //passing both meta data and file content for uploading
                RequestBody requestBody = new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("Metadata", null, requestBodyMetaData)
                        .addFormDataPart("Media", null, body)
                        .build();
                //Requesting the api
                Request request = new Request.Builder()
                        .url("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart")
                        .addHeader("Authorization", String.format("Bearer %s", accessToken))
                        .addHeader("Content-Type", "multipart/related; boundary=100")
                        .addHeader("Content-Length", size)
                        .addHeader("Accept", "application/json")
                        .post(requestBody)
                        .build();
                Response response = null;
                OkHttpClient client = new OkHttpClient();
                try {
                    response = client.newCall(request).execute();
                    String json = response.body().string();
                    successCode = String.valueOf(response.code());
                } catch (IOException e) {
                    e.printStackTrace();
                }

Comments

0

This is the complete example using googleapiclient

//variables
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;

now call this method on button click

//method to save file(Image type)
private void saveFileToDrive() {

    final Bitmap image = mBitmapToSave;
    Drive.DriveApi.newDriveContents(mGoogleApiClient)
            .setResultCallback(new ResultCallback<DriveContentsResult>() {

        @Override
        public void onResult(DriveContentsResult result) {

            if (!result.getStatus().isSuccess()) {
                Log.i("ERROR", "Failed to create new contents.");
                return;
            }


            OutputStream outputStream = result.getDriveContents().getOutputStream();
            // Write the bitmap data from it.
            ByteArrayOutputStream bitmapStream = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.PNG, 100, bitmapStream);
            try {
                outputStream.write(bitmapStream.toByteArray());
            } catch (IOException e1) {
                Log.i("ERROR", "Unable to write file contents.");
            }
            // Create the initial metadata - MIME type and title.
            // Note that the user will be able to change the title later.
            MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
                    .setMimeType("image/jpeg").setTitle("Android Photo.png").build();
            // Create an intent for the file chooser, and start it.
            IntentSender intentSender = Drive.DriveApi
                    .newCreateFileActivityBuilder()
                    .setInitialMetadata(metadataChangeSet)
                    .setInitialDriveContents(result.getDriveContents())
                    .build(mGoogleApiClient);
            try {
                startIntentSenderForResult(
                        intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
            } catch (SendIntentException e) {
                Log.i("ERROR", "Failed to launch file chooser.");
            }
        }
    });
}

@Override
protected void onResume() {
    super.onResume();
    if (mGoogleApiClient == null) {
        // Create the API client and bind it to an instance variable.
        // We use this instance as the callback for connection and connection
        // failures.
        // Since no account name is passed, the user is prompted to choose.
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }
    // Connect the client. Once connected, the camera is launched.
    mGoogleApiClient.connect();
}

@Override
protected void onPause() {
    if (mGoogleApiClient != null) {
        mGoogleApiClient.disconnect();
    }
    super.onPause();
}

Ref Upload image to a google drive using google drive api programatically in android

1 Comment

Hi Quick learner, thanks for your reply. I would like to inform you that the DriveApi is deprecated now and Google is going to stop that service by 6/Dec/2019. Google is suggesting to use Drive REST api only for any kind of API access. Could you please give me some solution on Google apies as you can see my question is related to Google Drive REST api only. Thanks once again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.