Ошибка при загрузке файла изображения на Google Drive с использованием REST API - PullRequest
0 голосов
/ 28 мая 2019

Я работаю с Google Drive впервые. Я пытаюсь загрузить файл jpg на мой диск Google через мое приложение. Я завершил авторизацию OAuth 2.0 для входа в учетную запись и разрешения диска. Я успешно загрузил файл на Google Диск, следуя инструкциям, приведенным здесь https://developers.google.com/drive/api/v3/manage-uploads?refresh=1

Проблема с загруженным файлом. Изображение не сохраняется там как изображение. Какой должна быть форма тела запроса здесь?

Вот фрагмент кода, который я использовал для загрузки файла изображения с помощью 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();
            }

Здесь «file» - это закодированная в Base64 строка изображения.

Это просто дает ожидаемый код http ok 200. Также необходимо знать, как установить заголовок для файла при загрузке на Google Drive.

Ответы [ 4 ]

1 голос
/ 28 мая 2019

Вы указали неверный тип контента в запросе. Должно быть

RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file);
0 голосов
/ 09 июня 2019

(Опубликовано от имени автора вопроса) .

Вот ответ на все мои вопросы.Вопросы были

  1. Создайте папку на диске Google с нужным именем.
  2. Загрузите файл (изображение / аудио / видео) в эту конкретную папку.

Начнем с пункта № 1.Вот рабочий код для создания папки на диске Google с нужным именем.Я хотел бы упомянуть еще одну вещь, связанную с авторизацией OAuth 2.0.Согласно руководству Google, я использовал код от Codelab.Вот ссылка для получения кода https://codelabs.developers.google.com/codelabs/appauth-android-codelab/?refresh=1#0 Область действия должна соответствовать API, предоставляемому Google для этой конкретной службы.Для меня это "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();
            }

Теперь вы должны получить идентификатор папки. Вот код для получения идентификатора папки.

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

Этот идентификатор папки необходимчтобы определить папку, в которую мы собираемся загрузить файл. Выберите файл из списка и затем передайте этот файл в формате byte [] этому коду. Здесь мы должны использовать mediatype как multipart, потому что если мы используем простую загрузку (медиа) мы не можем установить желаемое имя для загруженного файла.

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();
                }
0 голосов
/ 29 мая 2019

Спасибо всем вам за ваши усилия, особенно Coder. Я сделал это. Вот решение проблемы формата данных файла. Это просто настройка в заголовке в конструкторе запросов. Мы должны добавить Content-Type со значением «application / json» в заголовок запроса и тело запроса с «image / jpeg». Вот исправленный код ..

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

Я хотел бы упомянуть еще одну вещь, связанную с авторизацией OAuth 2.0. Согласно руководству Google, я использовал код от Codelab. Вот ссылка для получения кода https://codelabs.developers.google.com/codelabs/appauth-android-codelab/?refresh=1#0 Область действия должна соответствовать API, предоставляемому Google для этой конкретной службы. Для меня это "https://www.googleapis.com/auth/drive.file".

Но все же я застрял с именем файла в конце диска. Сохранение файлов с именем «Без названия». Не могли бы вы помочь мне в этом?

0 голосов
/ 28 мая 2019

Это полный пример с использованием googleapiclient

//variables
private GoogleApiClient mGoogleApiClient;
private Bitmap mBitmapToSave;

теперь вызывайте этот метод при нажатии кнопки

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

Ссылка Загрузить изображение на диск Google с помощью API Google Drive программно в Android

...