M5Stack(MicroPython)からrailsとActiveStorageの組み合わせを利用して画像ファイルをダウンロードしようとしたら苦戦をしたという話をしたいと思います。
TL;DR
現状のMicroPythonで使えるurequestsはリダイレクトに対応していません。そして、ActiveStorageは画像への直接のアクセスが現状できず、リダイレクトのリンクが表示されます。
つまり組み合わせるとつらい思いをします。
uurequestsを使えばもっと楽に解決できたみたいです。
環境に関して
MicroPythonへの変更方法に関しては今回は紹介しません。
MicroPythonとRail-APIとActiveStorage使って適当に作った感じです。バージョンとかは以下の通りです。
やりたかったこと
「サーバから画像ファイルをダウンロードして表示したい。」という目的でした。
コードを書いてみる
##M5Stackで実行したコード
まずはM5Stackのコードを一回ローカルに保存してから表示するというコードをシンプルにしたものを出します。
from m5stack import lcd
import urequests
with open('image.jpg', 'w') as outfile:
outfile.write(urequests.get('画像のURL').content)
lcd.image(0,0,'image.jpg')
その時は画像のリンクを表示するためにRailsでは以下のコードをコントローラーで記述していました。
class ImagesController < ApplicationController
include(Rails.application.routes.url_helpers)
# ~~~省略~~~
def show
# ~~~省略~~~
render json: {image_url: rails_blob_path(image)}
end
# ~~~省略~~~
end
問題発生
処理の途中で何やらエラーが出てしまいます。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "urequests.py", line 112, in get
File "urequests.py", line 100, in request
File "urequests.py", line 97, in request
NotImplementedError: Redirects not yet supported
どうやらActiveStorageは画像本体への直接のアクセスをさせないためにリダイレクトされるみたいです。ちょっと困りました。
解決策 その1
- urequestsを頑張ってリダイレクトに対応させる
- 辛い…
- 別の画像アップロードライブラリを使用する
- 一回作っちゃったのを変えるのが面倒くさい
で色々と悩んだのですが、ActiveStorageのドキュメントを読んでいたら何やら変換用に一時的にダウンロードするdownload
メソッドがあることに気が付きました。
これひょっとして、downloadしてきてsend_dataしてあげれば良いんじゃないかな?と思ったらバッチリ表示できました。その部分だけ抜き出したコードが下の通りになります。
send_data @image.download, :type => 'image/jpeg', :disposition => 'inline'
力技すぎてガシガシ叩かれると辛いので、一般的なWebサービスを作成する際には辞めたほうが良いと思います。
解決策その2(書いてるときに教わった)
redirectしても大丈夫なライブラリのuurequestsを利用しましょう。
phalconさんのレポジトリにuurequestsはあるのであるのでこちらをダウンロードして一緒にM5Stackに一緒に転送してimportすれば使用できます。
from uurequests
uurequests.get('https://example.com')
みたいに使うことができます。
まとめ
知らないものに知らないものをかけ合わせるとうまく対応出来ずに困りますという話でした。新しいことをやるときは全部一気にやるんじゃなくてちょっとずつやっていったほうが良いですね。