質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

firebase storageの複数画像アップロード機能を作成したい【react-native】

ug_o
ug_o

総合スコア39

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

1回答

0グッド

0クリップ

227閲覧

投稿2022/11/13 05:53

前提

react-native(expo)でInstagramのような画像投稿できる機能を作っております。
firebase strageに画像を保存する機能を作成したのですが、複数枚画像をアップロードすることができませんでした。
画像を複数アップロードするにはどのようにすれば良いでしょうか。
また、アップロード後の画像パスを取得してfirestoreにドキュメントを登録する処理も加えています。
よろしくお願いいたします。

発生している問題・エラーメッセージ

画像の配列をループで処理したが、画像の1枚目しかアップロードされず、当然firestoreにもドキュメントは作成されませんでした。

該当のソースコード

アップロード機能

firebase.ts

1 export const uploadImage = async (uri: string, path: string) => { 2 // uriをblobに変換 3 const localUri = await fetch(uri); 4 const blob = await localUri.blob(); 5 // storageにupload 6 const storage = getStorage(); 7 const strageRef = ref(storage, path); 8 9 let downloadUrl = ""; 10 try { 11 await uploadBytesResumable(strageRef, blob); 12 downloadUrl = await getDownloadURL(strageRef); 13 } catch (err) { 14 console.log(err); 15 } 16 return downloadUrl; 17 };

投稿ページ

CreatePost.tsx

1import React, { useEffect, useState, useContext } from "react"; 2import { StyleSheet, SafeAreaView, View, Image, Alert, FlatList } from "react-native"; 3import { setDoc } from 'firebase/firestore'; 4 5import { createPostRef, uploadImage } from "../lib/firebase"; 6import { MultiplePickImage} from "../lib/multiple-image-picker"; 7import { UserContext } from "../contexts/userContext"; 8import { ReviewsContext } from "../contexts/reviewsContext"; 9import { getExtention } from "../utils/file"; 10 11import { IconButton } from "../components/IconButton"; 12import { TextArea } from "../components/TextArea" 13import { StarInput } from "../components/StarInput" 14import { Button } from "../components/Button" 15import { Loading } from "../components/Loading" 16 17import { NativeStackNavigationProp } from "@react-navigation/native-stack"; 18import { RootStackParamList } from "../types/navigation"; 19import { RouteProp } from "@react-navigation/native"; 20import { serverTimestamp } from "firebase/firestore"; 21import { Post } from "../types/post"; 22 23type Props = { 24 navigation: NativeStackNavigationProp<RootStackParamList, "CreatePost">; 25 route: RouteProp<RootStackParamList, "CreatePost">; 26}; 27 28export const CreatePostScreen: React.FC<Props> = ({ 29 navigation, 30 route, 31}: Props) => { 32 const { post } = route.params; 33 const [text, setText] = useState<string>(""); 34 const [imgUrls, setImgUrls] = useState([]); 35 const [loading, setLoading] = useState<boolean>(false); 36 const { user } = useContext(UserContext); 37 38 useEffect(() => { 39 navigation.setOptions({ 40 headerLeft: () => ( 41 <IconButton name="x" onPress={() => navigation.goBack()} /> 42 ), 43 }); 44 }, [post]); 45 46 const onSubmit = async () => { 47 if(!text || !imgUrls) { 48 Alert.alert("レビューまたは画像がありません"); 49 return; 50 }; 51 52 setLoading(true); 53 let imgs = []; 54 //documentのIDを取得 55 const postDocRef = await createPostRef(); 56 imgUrls.map((img) => { 57 //storageのpathを決定 58 const ext = getExtention(img.uri); 59 const storagePath = `post/${postDocRef.id}/${postDocRef.id}.${ext}`; 60 //画像をstorageにアップロード 61 const downloadUrl = uploadImage(img.uri, storagePath); 62 imgs.push(downloadUrl); 63 }) 64 //postドキュメントを作成 65 const post = { 66 id: postDocRef.id, 67 user: { 68 name: user?.name, 69 id: user?.id, 70 imgUrl: user?.imgUrl 71 }, 72 text, 73 imgUrl: imgs, 74 updateAt: serverTimestamp(), 75 createdAt: serverTimestamp(), 76 } as Post; 77 await setDoc(postDocRef,post); 78 79 setLoading(false); 80 navigation.goBack(); 81 }; 82 83 const onPickImage = async () => { 84 const images = await MultiplePickImage(); 85 setImgUrls(images); 86 }; 87 return( 88 <SafeAreaView style={styles.container}> 89 <StarInput score={score} onChangeScore={(value) => setScore(value)} /> 90 <TextArea value={text} onChangeText={(value) => setText(value)} label="" placeholder="キャプションを書く" /> 91 <View style={styles.photoContainer}> 92 <IconButton name="camera" onPress={onPickImage} color="#ccc" /> 93 {!!imgUrls && 94 <FlatList 95 data={imgUrls} 96 keyExtractor={(item, index) => index.toString()} 97 numColumns={2} 98 99 renderItem={({ item }) => ( 100 <View> 101 <Image 102 source={{ uri: item.uri }} 103 style={styles.image} 104 /> 105 </View> 106 )} 107 />} 108 </View> 109 <Button text="投稿する" onPress={onSubmit} /> 110 <Loading visible={loading} /> 111 </SafeAreaView> 112 ); 113}; 114 115const styles = StyleSheet.create({ 116 container: { 117 flex: 1, 118 backgroundColor: "#fff", 119 }, 120 photoContainer: { 121 margin: 8 122 }, 123 image: { 124 width: 100, 125 height: 100, 126 margin: 8 127 } 128});

補足情報(FW/ツールのバージョンなど)

firebase: 9.9.2
expo: 46.0.0

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

自己解決

自己解決しました。
ループで1件ずつアップロードを実行し、Promise.allで正常に終わるのを待ちました。
返り値が配列で返ってくるので、その値をimgUrlに使用することでfirestoreにファイルURLを配列で登録することができました。

Typescript

1const result = await Promise.all(imageUrls.map(async(img, index) => { 2 //storageのpathを決定 3 const ext = getExtention(img.uri); 4 const storagePath = `reviews/${reviewDocRef.id}/${reviewDocRef.id}-${index}.${ext}`; 5 //画像をstorageにアップロード 6 const downloadUrl = await uploadImage(img.uri, storagePath); 7 return downloadUrl; 8 })) 9 console.log(result);

投稿2022/11/16 00:32

ug_o

総合スコア39

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

Cloud Firestore

Cloud Firestore は、自動スケーリングと高性能を実現し、アプリケーション開発を簡素化するように構築された NoSQLドキュメントデータベースです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。