0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

S3からGoogleのTeamDriveへデータをコピーした話

Last updated at Posted at 2020-02-29

背景

それほどニーズがあるかと思いませんが、S3にあるファイルを違うVenderのStorageにも保存しながら簡単ファイル共有できるようにしました。
GoogleDriveApiを使ってドキュメント通り対応したら難しくもなかったが、ファイル容量が大きいといろいろはまることもあった。再度、同じような実装するはないかと思います、念のためメモとして残して置きます。

したいこと

S3のデータをGoogleDriveへ自動的移行する。

やったこと

PythonでS3のバケットの中身を指定のチームドライブに移行しました。

実装詳細

  1. S3 からファイルをtmpにダウンロードします。
  2. ファイルすでにGdriveに存在するかどうかを確認する
  3. 存在している場合上書きする
  4. 存在しない場合は新規として追加する

事前準備

  • S3バケットに移行対象のファイルが存在する
  • GoogleClientId, GoogleClientSecretの準備 参考サイト
  • GoogleRefreshTokenの準備 参考サイト
  • 移行先GoogleDriveのFolderIdの準備

実際に実装したのこんなソースです。

# Download File from S3 to Local tmp Dir
# Upload a file to Google Drive

import os
import boto3
import json
import requests
import magic



## setting info
CONTENT_BUCKET_NAME = 'MY_S3_BUCKET_NAME'
CONTENT_BACKUP_KEY = 'MY_S3_BUCKET_KEY'
GOOGLE_CLIENT_ID = "XXXXXXXXXXXX.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET = "XXXXXXXXXXXX"
GOOGLE_REFRESH_TOKEN = "XXXXXXXXXXXX"
GOOGLE_FOLDER_ID = 'GOOGLE_FOLDER_ID'


s3 = boto3.resource('s3')
 
# Get the object from the event and show its content type
bucket = CONTENT_BUCKET_NAME
key = CONTENT_BACKUP_KEY
file_name = key.split("/")[1]
file_path = os.path.join("/tmp/"+ file_name)
s3.Object(bucket, key).download_file(file_path)
filesize = os.path.getsize(file_path)
fname, extension = os.path.splitext(file_name)

# refresh token
access_token_url = 'https://accounts.google.com/o/oauth2/token'
headers = {"Content-Type":"application/json","X-Accept":"application/json"}
refresh_token_request = {"grant_type":"refresh_token", "client_id": GOOGLE_CLIENT_ID, "client_secret": GOOGLE_CLIENT_SECRET, "refresh_token": GOOGLE_REFRESH_TOKEN}
access_token_request = requests.post(access_token_url,headers=headers,data=json.dumps(refresh_token_request))
access_token = access_token_request.json()['access_token']
print(access_token)

# check file already exist 
downloadUrl = "https://www.googleapis.com/drive/v3/files"
headers = {
    'Host':'www.googleapis.com',
    'Authorization': 'Bearer ' + access_token,
    'Content-Type':'application/json; charset=UTF-8',
    "X-Accept":"application/json"
}
qs= { "q": "'" + GOOGLE_FOLDER_ID + "' in parents and name='" + file_name + "' and trashed=false",
      "supportsAllDrives": True,
      "includeItemsFromAllDrives": True
    }

fileExistCheck = requests.get(downloadUrl, params=qs, headers=headers)
responseJsonFiles = fileExistCheck.json()['files']
searchResponseLength = len(responseJsonFiles)

#upload_file()
mime = magic.Magic(mime=True)
mimeType = mime.from_file(file_path) 

#folder_id = GOOGLE_FOLDER_ID
headers = {
    'Host':'www.googleapis.com',
    'Content-Length': str(filesize),
    'Authorization': 'Bearer ' + access_token,
    'Content-Type':'application/json; charset=UTF-8',
    'X-Upload-Content-Type': mimeType,
    'X-Upload-Content-Length': str(filesize)
}

with open(file_path, 'rb') as data:
  file_name= os.path.basename(file_path)
  metadata = {
    "name": file_name,
    "title": file_name,
    "parents": [GOOGLE_FOLDER_ID],
    'kind': 'drive#permission',
    "permissionDetails": [
      {
        "permissionType": "file",
        "role": "organizer"
      }
    ],
  }
 
 # No file exist. Post new one.
  if searchResponseLength < 1:
    postUrl = "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&supportsAllDrives=true"
    r = requests.post(postUrl, data=json.dumps(metadata), headers=headers)
    # data upload url
    uploadUrl = r.headers['Location']

    r2 = requests.post(uploadUrl, data=data, headers=headers)
  
  # file exist. Put to override
  else:
    fileId = responseJsonFiles[0]['id']
    metadata = {
      "filename": file_name,
      "name": file_name,
      "title": file_name,
      'kind': 'drive#permission',
      "permissionDetails": [
        {
          "permissionType": "file",
          "role": "organizer"
        }
      ]
    }
    
    putUrl = "https://www.googleapis.com/upload/drive/v3/files/" + fileId + "?uploadType=resumable&supportsAllDrives=true"
    r = requests.patch(putUrl, data=json.dumps(metadata), headers=headers)
    uploadUrl = r.headers['Location']
    r2 = requests.patch(uploadUrl, data=data, headers=headers)

終わりに

もっと改善点あるかと思いますが、これよりも簡単に実装する方法がありましたら是非コメントしてください。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?