###実現したいこと
複数の画像をカメラロールから選択、Firebase Storageへアップロード(メルカリの出品する際の画像選択)のイメージです。
###現状
画像を1枚選んでアップロードする場合は下記のコードでできています。
流れとしては、
①画像を選択する時にonPressAdd()が始まる
②uploadPostImg()の処理でFirebase Storageへの画像のアップロード
③画像のダウンロードURLがstateに書き込まれる
items collectionのドキュメントの中のphraseというフィールドとurlというフィールドにstorageのurlが入るようになっています。
画像を5枚まで選択できるようにしたいので、
ドキュメント items
フィールド phrase, url1(1枚目の画像のurl), url2(2枚目の画像のurl), url3, url4, url5
このようにしたいです。
ご教示いただけると幸いです。
###コード
javascript
1export default class Register extends Component<Props> { 2 constructor(props) { 3 super(props); 4 this.state = { 5 imgUrl: '', 6 phrase: '', 7 addedPost: [], 8 }; 9 } 10 11 // 投稿時の処理 12 async onPressAdd() { 13 await this.uploadPostImg(); 14 const { imgUrl, phrase, postIndex } = await this.state; 15 this.uploadPost(imgUrl, phrase, postIndex); 16 this.setState( 17 { 18 addedPost: [ 19 { 20 imgUrl, 21 phrase, 22 postIndex, 23 }, 24 ], 25 } 26 ); 27 } 28 29 onAddImagePressed = async () => { 30 const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); 31 if (status === 'granted') { 32 const result = await ImagePicker.launchImageLibraryAsync({ 33 allowsEditing: true, 34 mediaTypes: ImagePicker.MediaTypeOptions.Images, 35 }); 36 if (!result.cancelled) { 37 // ImageManipulatorでリサイズ処理 38 const actions = []; 39 actions.push({ resize: { width: 350 } }); 40 const manipulatorResult = await ImageManipulator.manipulateAsync( 41 result.uri, 42 actions, 43 { 44 compress: 0.4, 45 }, 46 ); 47 this.setState({ 48 imgUrl: manipulatorResult.uri, 49 }); 50 } 51 } 52 }; 53 54 uploadPostImg = async () => { 55 const metadata = { 56 contentType: 'image/jpeg', 57 }; 58 const postIndex = Date.now().toString(); 59 const storage = firebase.storage(); 60 const imgURI = this.state.imgUrl; 61 const response = await fetch(imgURI); 62 const blob = await response.blob(); 63 const uploadRef = storage.ref('images').child(`${postIndex}`); 64 65 // storageに画像を保存 66 await uploadRef.put(blob, metadata).catch(() => { 67 alert('画像の保存に失敗しました'); 68 }); 69 70 // storageのダウンロードURLをsetStateする 71 await uploadRef 72 .getDownloadURL() 73 .then(url => { 74 this.setState({ 75 imgUrl: url, 76 postIndex, 77 }); 78 }) 79 .catch(() => { 80 alert('失敗しました'); 81 }); 82 }; 83 84 // stateに入っているダウンロードURLなどをFirestoreに記述する 85 uploadPost(url, phrase, postIndex) { 86 Fire.shared.uploadPost({ 87 url, 88 phrase, 89 postIndex, 90 }); 91 } 92 93 render() { 94 return ( 95 <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}> 96 <Container> 97 <Header> 98 <Left /> 99 <Body> 100 <Title>商品登録</Title> 101 </Body> 102 <Right /> 103 </Header> 104 <View> 105 <TouchableOpacity 106 onPress={() => this.onAddImagePressed()} 107 > 108 {this.state.imgUrl ? ( 109 <Image source={{ uri: this.state.imgUrl }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 110 ) : ( 111 <Icon 112 name="camera-retro" 113 type="font-awesome" 114 size={50} 115 color="gray" 116 /> 117 )} 118 </TouchableOpacity> 119 <Item> 120 <Input 121 placeholder='phrase' 122 autoCapitalize={'none'} 123 onChangeText={phrase=> this.setState({ phrase })} 124 required 125 onPress={Keyboard.dismiss} 126 /> 127 </Item> 128 <Button 129 title="追加" 130 onPress={() => this.onPressAdd()} 131 /> 132 </View> 133 </Container> 134 </TouchableWithoutFeedback> 135 ); 136 } 137}
###書き換えているコード(途中まで)
javascript
1export default class Register extends Component<Props> { 2 constructor(props) { 3 super(props); 4 this.state = { 5 imgUrl1: '', 6 imgUrl2: '', 7 phrase: '', 8 addedPost: [], 9 }; 10 } 11 12 // 投稿時の処理 13 async onPressAdd() { 14 await this.uploadPostImg(); 15 const { imgUrl1, imgUrl2, phrase, postIndex } = await this.state; 16 this.uploadPost(imgUrl1, imgUrl2, phrase, postIndex); 17 this.setState( 18 { 19 addedPost: [ 20 { 21 imgUrl, 22 phrase, 23 postIndex, 24 }, 25 ], 26 } 27 ); 28 } 29 30 onAddImagePressed = async () => { 31 const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); 32 if (status === 'granted') { 33 const result = await ImagePicker.launchImageLibraryAsync({ 34 allowsEditing: true, 35 mediaTypes: ImagePicker.MediaTypeOptions.Images, 36 }); 37 if (!result.cancelled) { 38 // ImageManipulatorでリサイズ処理 39 const actions = []; 40 actions.push({ resize: { width: 350 } }); 41 const manipulatorResult = await ImageManipulator.manipulateAsync( 42 result.uri, 43 actions, 44 { 45 compress: 0.4, 46 }, 47 ); 48 this.setState({ 49 imgUrl: manipulatorResult.uri, 50 }); 51 } 52 } 53 }; 54 55 uploadPostImg = async () => { 56 const metadata = { 57 contentType: 'image/jpeg', 58 }; 59 const postIndex = Date.now().toString(); 60 const storage = firebase.storage(); 61 const imgURI = this.state.imgUrl; 62 const response = await fetch(imgURI); 63 const blob = await response.blob(); 64 const uploadRef = storage.ref('images').child(`${postIndex}`); 65 66 // storageに画像を保存 67 await uploadRef.put(blob, metadata).catch(() => { 68 alert('画像の保存に失敗しました'); 69 }); 70 71 // storageのダウンロードURLをsetStateする 72 await uploadRef 73 .getDownloadURL() 74 .then(url => { 75 this.setState({ 76 imgUrl: url, 77 postIndex, 78 }); 79 }) 80 .catch(() => { 81 alert('失敗しました'); 82 }); 83 }; 84 85 // stateに入っているダウンロードURLなどをFirestoreに記述する 86 uploadPost(url, phrase, postIndex) { 87 Fire.shared.uploadPost({ 88 url1, 89 url2, 90 phrase, 91 postIndex, 92 }); 93 } 94 95 render() { 96 return ( 97 <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}> 98 <Container> 99 <Header> 100 <Left /> 101 <Body> 102 <Title>商品登録</Title> 103 </Body> 104 <Right /> 105 </Header> 106 <View> 107 <TouchableOpacity 108 onPress={() => this.onAddImagePressed()} 109 > 110 {this.state.imgUrl1 ? ( 111 <Image source={{ uri: this.state.imgUrl1 }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 112 ) : ( 113 <Icon 114 name="camera-retro" 115 type="font-awesome" 116 size={50} 117 color="gray" 118 /> 119 )} 120 </TouchableOpacity> 121 <TouchableOpacity 122 onPress={() => this.onAddImagePressed()} 123 > 124 {this.state.imgUrl2 ? ( 125 <Image source={{ uri: this.state.imgUrl2 }} style={{ width: 100, height: 100, alignSelf: 'center' }} /> 126 ) : ( 127 <Icon 128 name="camera-retro" 129 type="font-awesome" 130 size={50} 131 color="gray" 132 /> 133 )} 134 </TouchableOpacity> 135 <Item> 136 <Input 137 placeholder='phrase' 138 autoCapitalize={'none'} 139 onChangeText={phrase=> this.setState({ phrase })} 140 required 141 onPress={Keyboard.dismiss} 142 /> 143 </Item> 144 <Button 145 title="追加" 146 onPress={() => this.onPressAdd()} 147 /> 148 </View> 149 </Container> 150 </TouchableWithoutFeedback> 151 ); 152 } 153}
あなたの回答
tips
プレビュー