7
6

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.

Rails × Heroku × Google Drive で無料でファイルアップローダー機能作る!

Last updated at Posted at 2021-03-12

Herokuで画像をアップロードすると問題が発生

Herokuでは画像をアップロードしてもスリープモードに入ると、画像が消えてしまう。

これを解決したい。

そこで調べて分かったことが、外部ストレージサービスを利用して、そこに画像をアップロードする。
という手順と分かりました。

どうしてもお金をケチりたい。

外部ストレージサービスとして
Amazon Storageを使ってアップロードするのが普通ですが、

クレジットカード登録が必要ですし、場合によってはお金がかかってしまいます。

そこでGoogleDriveにアップロードし、GoogleDriveの共有URLを使って画像表示させる。 これで無料に(15GBまで可能)アップロード機能が作れます。

GoogleDriveでファイルをアップロードするには

Google Cloud プラットフォームでやること

https://console.cloud.google.com/

にアクセスして、新しいプロジェクトを作成してください。

作成した後、 APIとサービスからOauth同意画面に移動し、ユーザの種類は外部にし、アプリ名などを入力します。公開ステータスは本番環境にしてください。

作成し終えたら、認証情報に移動してください。

image.png

認証情報を作成します。

OAuthクライアントIDを選択してください。

アプリケーションの種類は

ウェブ アプリケーション

承認済みのリダイレクト URIは https://ドメイン or http://ドメイン

などにしてください。

次にAPIを追加します。

image.png

ライブラリを選択してください。

Google Drive API, Google+ API を追加してください。

googleDriveにアクセスできるようにする。

さぁいよいよプログラミングの開始です。

Railsプロジェクトに移動し、Gemfileを開いてください

gem 'google_drive'

を追加したら、

bundle installを実行し、

Controllerに

(例)

         class PostsController < ApplicationController
	         require "google_drive"
             def index 
		       credentials = Google::Auth::UserRefreshCredentials.new(
		       client_id: "ここに先ほどGoogleCloudプラットフォームで取得したClient Idを追加",
		       client_secret: "ここに先ほどGoogleCloudプラットフォームで取得したClient SecretKEYを追加",
		       scope: [
		       "https://www.googleapis.com/auth/drive",
		       "https://spreadsheets.google.com/feeds/",
		       ],
		       redirect_uri: "http://localhost:3000")
               puts "ここにアクセスしてください---" + credentials.authorization_uri.to_s
               credentials.code = params[:code]
		       credentials.fetch_access_token!
               puts "REFRESH TOEKNゲットする---" + credentials.refresh_token.to_s
		       @session = GoogleDrive.login_with_oauth(credentials.access_token)
             end
         end

こうすると 

ここにアクセスしてください---https:// ...

と出るはずなので

そのURLにアクセスしてください。

するとアカウントを選択と出てきます。

GoogleDriveを使いたいアカウントでログインし、クリックすると

権限の付与が出てくるので、
許可してください。

するとlocalhost:3000に飛ばされてパラメーターにcodeがくっついてきます。

そのcodeを

credentials.code = params[:code]

のようにしてcredentials.codeに代入しています。

credentials.fetch_access_token!

このコードにより、アカウントが認証されAccessTokenなどが返ってきます。

その返ってきたAccessTokenで

@session = GoogleDrive.login_with_oauth(credentials.access_token)

これでRailsでGoogleDriveを扱えます!

しかし、ここでとある問題が

「こんなのいちいち認証してられない!」

なので、Refresh tokenというものを取得し自動認証させます。

REFRESH TOEKNゲットする--- ・・・・・・"

と表示され、Refresh tokenが取得できるはずなのでコピーしてメモしておいてください。

コードを修正します。

	    credentials = Google::Auth::UserRefreshCredentials.new(
              client_id: "ここに先ほどGoogleCloudプラットフォームで取得したClient Idを追加",
              client_secret: "ここに先ほどGoogleCloudプラットフォームで取得したClient SecretKEYを追加",
	          scope: [
		        "https://www.googleapis.com/auth/drive",
		        "https://spreadsheets.google.com/feeds/",
		  ],
		      redirect_uri: "http://localhost:3000",
		      refresh_token: "先ほどメモしたRefresh Token")

	    credentials.update!(access_token: credentials.refresh_token)	
		
		credentials.fetch_access_token!
		@session = GoogleDrive.login_with_oauth(credentials.access_token)

これを

class PostsController < ApplicationController

  before_action :get_session

  def index 

  end

  private
    def get_session
        credentials = Google::Auth::UserRefreshCredentials.new(
              client_id: "ここに先ほどGoogleCloudプラットフォームで取得したClient Idを追加",
              client_secret: "ここに先ほどGoogleCloudプラットフォームで取得したClient SecretKEYを追加",
              scope: [
                "https://www.googleapis.com/auth/drive",
                "https://spreadsheets.google.com/feeds/",
          ],
              redirect_uri: "http://localhost:3000",
              refresh_token: "先ほどメモしたRefresh Token")

        credentials.update!(access_token: credentials.refresh_token)    

        credentials.fetch_access_token!
        @session = GoogleDrive.login_with_oauth(credentials.access_token)
    end
end

とbefore_actionで@sessionを渡してあげれば安心ですね!

これで毎回認証しなきゃいけないめんどくさい!問題は解決しました。

google-drive-rubyの基本

ファイル フォルダー すべて取得

@session.files

#ファイル一つ一つ取得↓

@session.files.each do |file|
  p file.title
end

ファイル フォルダー検索

#名前で検索
 @session.file_by_title("ファイル名 or フォルダ名")
#IDで検索
 @session.file_by_id("ファイルID")

ファイルアップロード

```rb @session.upload_from_file("ファイルのパス")

#フォルダの中にアップロード↡
folder = @session.file_by_title("フォルダ名")
folder.upload_from_file("ファイルのパス")

<h4>ファイル or フォルダのIDやタイトルを取得</h4>
```rb
#アップロードしたファイルのID タイトル を取得する
file = @session.upload_from_file("ファイルのパス")
p file.id
p file.title

ファイルを更新


@session.update_file("ファイルID")

ファイルを削除(完全に)

@session.drive_service.delete_file("ファイルID", supports_all_drives: true)

あとは公式ドキュメントやその他サイトをご覧ください。



いよいよアップロードする。

さぁ基本を知ったうえでアップロード機能をさっそく作成してみましょう。

1.ファイルをアップロードするためのフォルダを作る

GoogleDriveを開き、新規→フォルダ

今回はtest-uploadとします。

作ったフォルダを共有する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565846/5f6be157-006e-8d5e-fc96-00bc16fa0db4.png)

共有を押し、
image.png

リンクを取得の リンクを知っている全員に変更を押してください。
image.png

するとこのようになるので完了を押してください。

2.Carrierwaveでファイルをアップロードできるようにする

ここに関しては割愛させていただきます。

参考にしてください。
https://qiita.com/Inp/items/cc447237e23bf10d159e

3.Carrierwaveでアップロードして、saveした後にGoogleDriveにアップロードする

例 Fileをアップロードし、保存しGoogleDriveにもアップロードし、GoogleドライブにアップロードしたファイルのIDをデータベースに保存しておく。

class TweetsController < ApplicationController
  before_action :get_session
  def create
     file = params[:post][:file]
     @post = Post.create(file: file)
     folder = @session.file_by_title("test-upload") #GoogleDriveのtest-uploadフォルダを探す
     file_ext = File.extname(@post.file.file.original_filename) #拡張子を取得
     file_find = folder.upload_from_file(@post.file.current_path, "test-upload-#{@post.id}-file#{file_ext}") #ファイルをアップロード!
     @post.update(google_drive_file_id: file_find.id) #ファイルIDを保存しておく。
     redirect_to root_path
  end

  private
	def get_session
		credentials = Google::Auth::UserRefreshCredentials.new(
		client_id: ENV["CLIENTID"],
		client_secret: ENV["CLIENTSECRET"],
		scope: [
		"https://www.googleapis.com/auth/drive",
		],
		redirect_uri: "http://localhost:3000",
		refresh_token: ENV["REFRESH_TOKEN"])
		credentials.update!(access_token: credentials.refresh_token)				
		credentials.fetch_access_token!
		@session = GoogleDrive.login_with_oauth(credentials.access_token)
	end
end

これでアップロードが完了!

ですが、やはりなかなかアップロードにお時間がかかりますな..

アップロードしたファイルを表示

index.html.erb
<% @posts.each do |post| %>
 <%= image_tag "https://drive.google.com/uc?id=#{post.google_drive_file_id}" %>
<% end %>

これでできるはずです!

あとがき

やはり、アップロード時間はAmazon Storageには劣るらしいのでそこは仕方がないですね..

動画でも音楽でも画像でもテキストファイルでもなんでもアップロードできるようになります。(しかし、大きなファイルはアップロードできません。)

僕が一番苦戦したところはアカウント認証させて、GoogleDriveをRailsで操作できるようにするところです..

参考になる記事が少ないのもあり、数時間も格闘しました...

この記事を書くのにもかなりの時間を費やしました。 僕はまだ中学生なのでクレジットカードを持てる年齢でもないのでこの方法で試してみたかったのです。

あまり説明がうまくできなくて申し訳ございません。 ですが、少しは役に立ててもらったらうれしいです。

参考

7
6
0

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
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?