Загрузка изображения с Android на GCS
Я пытаюсь загрузить изображение с Android непосредственно в хранилище облачных хранилищ Google. Но API, похоже, не работает. У них есть примеры Java, которые привязаны к движку App. Я не вижу образца, который, как доказано, работает на Android.
На Android я попытался использовать json api для загрузки изображения. Я могу загрузить объект изображения, но он кажется поврежденным. Более того, генерация маркера аутентификации тоже кажется сложной.
Я поражен этим прямо сейчас. Кто-нибудь на этой земле когда-либо пытался загрузить изображение/видео с Android с помощью Java-клиента или Json API и преуспел? Может кто-нибудь указать мне в правильном направлении, пожалуйста. Это очень разочаровывает опыт работы с этим хранилищем api от Google. Пожалуйста, поделитесь своими впечатлениями, если кто-то это сделает.
Ниже приведен код, который я пытаюсь использовать для Android, пытаясь использовать API GCS JSON.
private static String uploadFile(RichMedia media) {
DefaultHttpClient client = new DefaultHttpClient();
Bitmap bitmap = BitmapUtils.getBitmap(media.getLocalUrl());
HttpPost post = new HttpPost(GCS_ROOT + media.getLocalUrl() + "_" + System.currentTimeMillis());
if(media.getType() == RichMedia.RichMediaType.PICTURE) {
post.setHeader("Content-Type", "image/jpeg");
} else {
post.setHeader("Content-Type", "video/mp4");
}
post.setHeader("Authorization", "AIzaSyCzdmCMwiMzl6LD7R2obF0xSgnnx5rEfeI");
//post.setHeader("Content-Length", String.valueOf(bitmap.getByteCount()));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
try {
post.setEntity(new StringEntity(new Gson().toJson(byteArray).toString()));
HttpResponse response = client.execute(post);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String eachLine = null;
StringBuilder builder = new StringBuilder();
while ((eachLine = reader.readLine()) != null) {
builder.append(eachLine);
}
L.d("response = " + builder.toString());
JSONObject object = new JSONObject(builder.toString());
String name = object.getString("name");
return name;
} catch (IOException e) {
L.print(e);
} catch (JSONException e) {
L.print(e);
}
return null;
}
Здесь я столкнулся с двумя проблемами.
-
Файл, загруженный на сервер, поврежден. Это не тот же образ, который я загрузил. Это текущее значение.
-
Ключ авторизации истекает очень часто. В моем случае я использую код auth, созданный gsutil.
Ответы
Ответ 1
Поскольку никто не отвечает на этот вопрос, позвольте мне уточнить, как я решил эту проблему. Я закончил этот проект https://github.com/pliablematter/simple-cloud-storage.
Я могу загрузить Pictures/Videos в GCS из своего приложения для Android.
Ответ 2
Исправлено для Android:
Конфигурация Android Studio:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile files('libs/android-support-v4.jar')
compile files('google-play-services.jar')
compile 'com.wu-man:android-oauth-client:0.0.3'
compile 'com.google.apis:google-api-services-storage:v1-rev17-1.19.0'
compile(group: 'com.google.api-client', name: 'google-api-client', version:'1.19.0'){
exclude(group: 'com.google.guava', module: 'guava-jdk5')
}
}
AndroidManifiest:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
Основная реализация:
new AsyncTask(){
@Override
protected Object doInBackground(Object[] params) {
try {
CloudStorage.uploadFile("bucket-xxx", "photo.jpg");
} catch (Exception e) {
if(DEBUG)Log.d(TAG, "Exception: "+e.getMessage());
e.printStackTrace();
}
return null;
}
}.execute();
Класс CloudStorage:
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.StorageObject;
public static void uploadFile(String bucketName, String filePath)throws Exception {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard,filePath);
InputStream stream = new FileInputStream(file);
try {
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType,stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(file.getName());
insert.execute();
} finally {
stream.close();
}
}
private static Storage getStorage() throws Exception {
if (storage == null) {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(ACCOUNT_ID_PROPERTY) //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential).setApplicationName(APPLICATION_NAME_PROPERTY)
.build();
}
return storage;
}
private static File getTempPkc12File() throws IOException {
// xxx.p12 export from google API console
InputStream pkc12Stream = AppData.getInstance().getAssets().open("xxx.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}
Ответ 3
Этот фрагмент кода работает для меня отлично подходит для загрузки файлов с Android непосредственно в GCS.
File file = new File(Environment.getExternalStorageDirectory(), fileName);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
FileBody filebody = new FileBody(file,ContentType.create(mimeType), file.getName());
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("file", filebody);
httppost.setEntity(multipartEntity.build());
System.out.println( "executing request " + httppost.getRequestLine( ) );
try {
HttpResponse response = httpclient.execute( httppost );
Log.i("response", response.getStatusLine().toString());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
httpclient.getConnectionManager( ).shutdown( );
Класс MultipartEntityBuilder не включен в стандартные библиотеки Android, поэтому вам нужно загрузить httpclient и включить в свой проект.
Ответ 4
Ответ на Hpsaturn работал у меня. Он пропустил ответ на несколько моментов. Как получить идентификатор учетной записи службы и файл p12. Для получения этих 2 откройте console.developers.google.com и выберите свой проект. Включить API облачных хранилищ. Появится сообщение для создания учетных данных. Перейдите к учетным данным в диспетчере API и создайте учетные данные, выбрав ключ учетной записи службы и следуя деталям на изображении. На этом экране вы получите идентификатор учетной записи службы и файл p12.
![введите описание изображения здесь]()
Hpsaturn также пропустил упоминание AppData, который является вашим пользовательским классом приложений, определенным в манифесте. Для удобства я прилагаю здесь весь класс CloudStorage.
package com.abc.xyz.utils;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import com.abc.xyz.app.AppController;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.StorageObject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wjose on 8/20/2016.
*/
public class CloudStorage {
private static final String TAG = "CloudStorage";
public static void uploadFile(String bucketName, String name, Uri uri)throws Exception {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
//File file = new File(sdcard,filePath);
File file = new File(uri.getPath());
InputStream stream = new FileInputStream(file);
try {
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType,stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(name);
StorageObject obj = insert.execute();
Log.d(TAG, obj.getSelfLink());
} finally {
stream.close();
}
}
static Storage storage = null;
private static Storage getStorage() throws Exception {
if (storage == null) {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId("[email protected]") //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential).setApplicationName("MyApp")
.build();
}
return storage;
}
private static File getTempPkc12File() throws IOException {
// xxx.p12 export from google API console
InputStream pkc12Stream = MyApplication.getInstance().getAssets().open("xxxyyyzzz-0c80eed2e8aa.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}
}
btb, я использовал только следующую зависимость в gradle.
compile 'com.google.apis: google-api-services-storage: +'
Ответ 5
Я пробовал все вышеупомянутые ответы, и никто из них не работал у меня прямо из коробки.
Вот что я сделал, чтобы заставить его работать (только путем редактирования из приведенных выше комментариев):
package Your page name;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Environment;
import android.util.Log;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;
import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.StorageObject;
import java.io.File;
import java.io.*;
import java.io.InputStream;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
public class CloudStorage {
static Activity activity=null;
//http://stackoverflow.com/info/18002293/uploading-image-from-android-to-gcs
static Storage storage=null;
public static void uploadFile(Activity activity2,String bucketName, String filePath)
{
activity=activity2;
try {
Storage storage = getStorage();
StorageObject object = new StorageObject();
object.setBucket(bucketName);
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(filePath);
InputStream stream = new FileInputStream(file);
try {
Log.d("Alkamli","Test");
String contentType = URLConnection.guessContentTypeFromStream(stream);
InputStreamContent content = new InputStreamContent(contentType, stream);
Storage.Objects.Insert insert = storage.objects().insert(bucketName, null, content);
insert.setName(file.getName());
insert.execute();
} finally {
stream.close();
}
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
e.printStackTrace();
}
}
private static Storage getStorage() {
try {
if (storage == null)
{
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<String>();
scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
Credential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId("Service-Email-Address") //Email
.setServiceAccountPrivateKeyFromP12File(getTempPkc12File())
.setServiceAccountScopes(scopes).build();
storage = new Storage.Builder(httpTransport, jsonFactory,
credential)
.build();
}
return storage;
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
}
Log.d("Alkamli","Storage object is null ");
return null;
}
private static File getTempPkc12File() {
try {
// xxx.p12 export from google API console
InputStream pkc12Stream = activity.getResources().getAssets().open("Service-key.p12");
File tempPkc12File = File.createTempFile("temp_pkc12_file", "p12");
OutputStream tempFileStream = new FileOutputStream(tempPkc12File);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = pkc12Stream.read(bytes)) != -1) {
tempFileStream.write(bytes, 0, read);
}
return tempPkc12File;
}catch(Exception e)
{
class Local {}; Log.d("Alkamli","Sub: "+Local.class.getEnclosingMethod().getName()+" Error code: "+e.getMessage());
}
Log.d("Alkamli"," getTempPkc12File is null");
return null;
}
}
Я только редактировал несколько строк, чтобы заставить его работать для меня и для зависимостей в gradle. Вам понадобятся только эти три. (Имейте в виду, что если вы используете все goen depenacnes, которые могут повредить весь ваш проект, в моем случае некоторые из функций Android не будут работать больше)
compile 'com.google.api-client:google-api-client:1.20.0'
compile 'com.google.oauth-client:google-oauth-client-jetty:1.20.0'
compile 'com.google.apis:google-api-services-storage:v1-rev17-1.19.0'