🖌️
【Flutter】file_pickerのライブラリを使用して画像のアップロードを実装
概要
Flutterでファイルのアップロード機能を実装するとなると、いくつか実装の選択肢があると思います。
少し調べた結果、file_pickerというライブラリが、複数のプラットフォーム(iOSやWebなど)に対応して良さそうでした。今回これを使って、画像のアップロードの実装メモを残しておきます。
前提
- 使用したFlutterのバージョンは3.3.10です。
- 使用したfile_pickerのバージョンは5.2.5です。
- Webで動作確認を行っています。
実装サンプル
まずはファイルの選択部分の実装です。選択したファイルをstateに格納します。
class SampleUploadWidget extends StatefulHookConsumerWidget {
const SampleUploadWidget({super.key});
SampleUploadState createState() => SampleUploadState();
}
class SampleUploadState extends ConsumerState<SampleUploadWidget> {
final _formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
// 選択したファイルを格納するstate
final imageFileState = useState<PlatformFile?>(null);
Future<void> selectImage() async {
// file_pickerのライブラリを使用してファイルを取得
var result = await FilePicker.platform.pickFiles();
if (result != null) {
imageFileState.value = result.files.first;
} else {
// User canceled the picker
}
}
Future<void> uploadFile() async {
// ファイルをAPIで送信する処理(ソースの内容は後述)
if (imageFileState.value != null) {
var res = await UploadApiService.uploadFile(imageFileState.value);
}
}
return Center(
child: Form(
key: _formKey,
child: Column(
children: [
// ファイルを選択した場合はImageを表示
if (imageFileState.value != null)
Column(children: [
SizedBox(
width: 150,
height: 150,
child: Image.memory(imageFileState.value!.bytes!)),
const SizedBox(height: 20),
]),
ElevatedButton(
onPressed: () async => {
// ファイルの選択処理
selectImage()
},
style: ElevatedButton.styleFrom(
fixedSize: const Size(250, 50),
backgroundColor: const Color.fromARGB(255, 102, 100, 100),
),
child: const Text('ファイル選択'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async => {
// アップロード処理
await uploadFile()
},
style: ElevatedButton.styleFrom(fixedSize: const Size(250, 50)),
child: const Text('アップロード'),
),
],
),
),
);
}
}
次は選択したファイルをAPIでPOST送信する処理です。
FlutterのFileとXFileとの違いの記事を参考にして、ファイルをバイト形式にしてMultipartFile.fromBytes
を使用して送信します。
class UploadApiService {
static Future<Response> uploadFile(PlatformFile fileResult) async {
var url = Uri.parse("${dotenv.get('API_URL')}/fileUpload");
var request = http.MultipartRequest(
"POST",
url,
);
// ファイル項目を追加
var multipartFile = http.MultipartFile.fromBytes(
"sampleFile", fileResult.bytes!, filename: fileResult.name);
request.files.add(multipartFile);
// Post送信
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
return response;
}
}
Discussion