2013년 3월 28일 목요일

[Android][Google Cloud Storage] Upload A File to Google Cloud Storage in Android

Android 폰에서 생성이 되는 data file들을 자동으로 공유 받기 위해서 cloud server를 이용할 수 있다. 대표적인 storage server로는 Amazon S3, Google Cloud Storage, MS Azure등이 있다. 여기선 Google Cloud Storage(GS)를 사용해서, 휴대폰의 데이터를 server로 upload 한는 방법을 정리해 보겠다.
GS 사용 관련 기본적인 사항은 여기에서 확인 할 수 있다. Google 의 많은 서비스 들과는 달리, GS는 초기 5GB 바이트 까지 무료사용 할 수 있지만, 서비스를 activate하기 위해선 billing 정보를 먼저 등록해야 한다. Google APIs Console 사이트의 Services 탭에서 Google Cloud Storage를 on 시키고 Billing 정보를 입력한 다음 API Access 탭에서 Service account 하나 만들자. Google service들을 사용하기 위해선 사용을 원하는 client(여기선 android application)이 일련의 인증과정을 거쳐서 authentication을 먼저 획득해야 한다. 다양한 종류의 인증 방법이 존재하나, 여기서는 사용자의 interaction 없이, 우리가 만들 application이 스스로 access 권한을 획득해서 GS를 사용해야 하므로 service account를 생성하도록 한다.

Service Account를 생성하면, 우리는 private key(.p12) 파일과(개인 PC에 저장) service account에 대한 EMAIL address를 발급받게 된다. 이 두가지를 가지고 GS service에 접근할 수 있는 권한을 획득할 수 있다.
String SERVICE_ACCOUNT_EMAIL = "4XXXe@developer.gserviceaccount.com";
String BUCKET_NAME = "my_bucket_name";
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.full_control";
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
String KeyFile = "privatekey.p12";

File privateKey = new File(keyFile);
GoogleCredential credential = new GoogleCredential.Builder()
 .setTransport(HTTP_TRANSPORT)
 .setJsonFactory(JSON_FACTORY)
 .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
 .setServiceAccountScopes(STORAGE_SCOPE)
 .setServiceAccountPrivateKeyFromP12File(privateKey)
 .build();

여기에서 중요한 것은 SERVICE_ACCOUNT_EMAIL에는 service account 생성에서 발급된 EMAIL address를 넣어주고, KeyFile 역시 service account시에 발급된 key file을 지정해 준다.

GS는 데이터가 저장되는 공간을 bucket단위로 관리한다. Bucket에 저장된 file 리스트에 대한 정보를 얻기위해선 HTTP GET method를 이용한다.
String URI = "https://storage.googleapis.com/" + BUCKET_NAME;
GenericUrl url = new GenericUrl(URI);
try {
 HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(credential);
 HttpRequest request = requestFactory.buildGetRequest(url);
 HttpResponse response = request.execute();
 System.out.println(response.parseAsString());
} catch (IOException e) {
 e.printStackTrace();
}

위의 예제에서 url에 file name을 추가하게 되면, 지정된 file을 download할 수 있다.
String fileName = "downloadFile.file"
String URI = "https://storage.googleapis.com/" + BUCKET_NAME + "/";
GenericUrl url = new GenericUrl(URI);
url.appendRawPath(fileName);
try {
 HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(credential);
 HttpRequest request = requestFactory.buildGetRequest(url);
 HttpResponse response = request.execute();
 File mediaFile = new File(fileName);
 OutputStream out = new FileOutputStream(mediaFile);
 response.download(out);
} catch (IOException e) {
 e.printStackTrace();
}

File delete code는 HTTP DELETE method를 이용한다.
String fileName = "deleteFile.file"
String URI = "https://storage.googleapis.com/" + BUCKET_NAME + "/";
GenericUrl url = new GenericUrl(URI);
url.appendRawPath(fileName);
try {
 HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(credential);
 HttpRequest request = requestFactory.buildDeleteRequest(url);
 HttpResponse response = request.execute();
 System.out.println(response.parseAsString());
} catch (IOException e) {
 e.printStackTrace();
}

File upload를 위해선 HTTP PUT method를 이용한다.
String fileName = "uploadFile.file"
String URI = "https://storage.googleapis.com/" + BUCKET_NAME + "/";
GenericUrl url = new GenericUrl(URI);
url.appendRawPath(fileName);
try {         
 File mediaFile = new File(fileName);
 InputStreamContent mediaContent =
 new InputStreamContent("text/plain", //"image/jpeg"
  new BufferedInputStream(new FileInputStream(mediaFile)));
 mediaContent.setLength(mediaFile.length());

 HttpRequestFactory requestFactory = HTTP_TRANSPORT.createRequestFactory(credential);
 HttpRequest postrequest = requestFactory.buildPutRequest(url, mediaContent);
 HttpResponse response = postrequest.execute();
} catch (IOException e) {
 System.err.println(e.getMessage());
}

위의 코드는 google site에서 제공된 sample을 추가 보완하여 작성하였다