はじめに
現在作成しているアプリでGoogle Drive上の画像を読み込みたいと思い、実装してみたのですが問題発生。
var url = "https://drive.google.com/uc?export=view&id=$fileId";
var downloadImage = Image.network(url,
headers: {
"Authorization": "Bearer $accessToken"
},
loadingBuilder: (context, child, loadingProgress) {
if(loadingProgress != null){
return _noImage;
}
return child;
},
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if(!wasSynchronouslyLoaded && frame == 0){
// ロード完了
}
return child;
},
errorBuilder: (context, error, stackTrace) {
return _noImage;
},
);
これを実行すると以下のエラーが発生する。
Exception: Invalid image data
Exception: Invalid image data
#0 _futurize (dart:ui/painting.dart:6637:5)
#1 ImageDescriptor.encoded (dart:ui/painting.dart:6494:12)
#2 instantiateImageCodecWithSize (dart:ui/painting.dart:2291:60)
#3 PaintingBinding.instantiateImageCodecWithSize (package:flutter/src/painting/binding.dart:182:15)
#4 NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:153:22)
<asynchronous suspension>
これを解決するのが今回のお話です。
Goodle Driveで提供されるURL
共有のURL
Google Driveで共有の際提供されるURLは
https://drive.google.com/file/d/{fileId}/view?usp=drive_link
になります。
このURLをChromeで確認するとこんな感じでいっぱい通信が行われます。
おそらくですが、共有で提供されるリンクでは、最初にHTTP Status 200で返却される内容がHTMLなので失敗すると予想されます。
ダウンロードのURL
では次にダウンロードで使用されるURLを確認します。
URLは以下の通りです。
https://drive.google.com/uc?export=view&id={fileId}
このURLをChromeで確認すると、複数の通信が発生していることがわかります。
ただ、リダイレクトされまくったあとの200のヘッダを見ると Content-Type:image/jpeg で返却されているので、よさそうに見えます。
しかし実際には Exception: Invalid image data が発生します。
対象画像の共有の設定を リンクを知っている全員 に変更すると表示されました。
認証情報を付与してリクエストできれば、共有設定を リンクを知っている人全員 にしなくても行けそうですが、手段がわからないので、現段階ではこれで行くしかない。
var url = "https://drive.usercontent.google.com/uc?id=$fileId&export=download";
var downloadImage = Image.network(url,
headers: {
"Authorization": "Bearer $accessToken"
},
loadingBuilder: (context, child, loadingProgress) {
if(loadingProgress != null){
return _noImage;
}
return child;
},
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if(!wasSynchronouslyLoaded && frame == 0){
// ロード完了
}
return child;
},
errorBuilder: (context, error, stackTrace) {
return _noImage;
},
);
まとめ
- Image.network で指定するURLはダウンロードで使用するURL
- 画像の共有設定は リンクを知っている全員 にする