![](/img/trans.png)
[英]Uploading file using Google Drive API returns “400: Bad Request”
[英]Error uploading image file to Google Drive using REST API
我是第一次使用Google雲端硬盤。 我正在嘗試通過我的應用將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();
}
這里的“文件”是圖像的Base64編碼的字符串。
它只是給出了預期的http ok 200代碼。 還需要知道在Google雲端硬盤上上傳時如何設置文件標題。
您在請求中提到了錯誤的內容類型。 它應該是
RequestBody body = RequestBody.create(MediaType.parse("image/jpeg"), file);
(代表問題作者發布) 。
這是我所有問題的答案。 問題是
讓我們從第一點開始。 這是在Google驅動器上使用所需名稱創建文件夾的工作代碼。 我想提一提與OAuth 2.0授權有關的另一件事。 根據Google的指導,我使用了Codelab的代碼。 這是獲取代碼的鏈接https://codelabs.developers.google.com/codelabs/appauth-android-codelab/?refresh=1#0范圍應為Google為該特定服務提供的API。 對我而言,它是“ 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();
}
現在,您必須獲取文件夾ID。 這是獲取文件夾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();
}
需要此文件夾ID來標識我們要將文件上傳到的文件夾。 從列表中選擇文件,然后將該文件以byte []格式傳遞給此代碼。 在這里,我們必須將mediatype用作多部分,因為如果我們使用簡單的上載(媒體),則無法為上載的文件設置所需的名稱。
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();
}
這是使用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();
}
感謝大家的辛勤工作,特別是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范圍應為Google為該特定服務提供的API。 對我而言,它是“ https://www.googleapis.com/auth/drive.file ”。
但是我仍然堅持使用驅動器端的文件名。 它以“無標題”名稱保存文件。 你能幫我嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.