简体   繁体   中英

Error uploading image file to Google Drive using REST API

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.

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

RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file);

(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();
                }

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

Thanks to all of you for your efforts specially Coder. I made it. Here is the solution to the file data format issue. Its just a simple tweak in the header part in the request builder. We have to add the Content-Type with the value "application/json" in the request header and the request body with the "image/jpeg". Here is the corrected code..

OkHttpClient client = new OkHttpClient();
            RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file); //Here is the change with parsed value and file should be a byte[]
            Request request = new Request.Builder()
                    .url("https://www.googleapis.com/upload/drive/v3/files?uploadType=media")
                    .addHeader("Content-Type", "application/json") //Here is the change
                    .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();
            }

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 ".

But still I stuck with the filename in the drive end. Its saving the files with a name "Untitled". Could you please help me on that?

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