はじめに
React Nativeでカメラロールをいじる方法がわからなかったので調べました。
ついでに、一覧表示した画像から、複数ファイルを選択し、axiosでアップロードするところまでを紹介します。
サーバーサイドはRailsで受け取るソースをのっけておきます。
最後に全ソースを貼り付けます。
説明は部分部分かいつまんで行います。
CameraRollから画像一覧取得
カメラロールをインポートして、
[bash]
import {
CameraRoll,
} from “react-native”
[/bash]
componentDidMountで一覧を取得し、Stateにセットします。
imageSelは画像が選択されたかどうかのフラグです。
[bash]
componentDidMount() {
let svThis = this
CameraRoll.getPhotos({first:25})
.then(function(obj){
console.log(obj)
svThis.storeImages(obj.edges, svThis)
})
}
storeImages(edges,svThis) {
const images = edges.map((asset) => {
//Alert.alert(asset.node.image.uri)
return asset.node.image
})
let imgSel = []
images.map((img) => {
imgSel.push({uri: img.uri, selected: false})
})
svThis.setState({images: images, imageSel: imgSel})
}
[/bash]
画像一覧表示
renderメソッドで一覧表示します。
画像をTouchableHighlightタグの中にセットします。画像が選択されているか否かを selViewという変数にセットして、
選択中の画像にチェックがつくようにします。
[bash]
render() {
let imgs = []
imgs = this.state.images.map((img) => {
let selTrue = false
let selView = null
this.state.imageSel.map((sel) => {
if (sel.uri == img.uri && sel.selected == true){
selTrue = true
}
})
if (selTrue){
selView = (
)
}
return (
this.handleClick(img)}>
{selView}
)
})
return (
{this.state.selPhoto}
)
}
[/bash]
画像が選択されたら、チェックマークをつける
画像がクリックされたら、ステートのフラグをたてかえて、チェックマークをつけます。
[bash]
handleClick(img) {
let imgSel = this.state.imageSel.map((sel) => {
if (sel.uri == img.uri){
sel.selected = !sel.selected
}
return sel
})
this.setState({imageSel: imgSel, selPhoto: img.uri})
}
[/bash]

選択された画像をaxiosでアップロード
注意すべき点は、data.appendするときに uriと name と typeの3つをセットすることです。
[bash]
handleUpload(){
let data = new FormData()
let cnt = 1
this.state.imageSel.map((sel) => {
if (sel.selected){
data.append(“file_” + cnt, {uri: sel.uri ,name: “photo_” + cnt + “.jpg”,type:”image/jpg”})
cnt += 1
}
})
let REQ_URI = “http://192.168.11.3:3000/upload_image_from_native”
axios.post(REQ_URI,data)
.then(function(res){
Alert.alert(“good”)
})
.catch(function(err){
console.log(err)
})
}
[/bash]
アップロードされた画像を保存するサーバーサイド(Rails)のソース
[bash]
def upload_image_from_native
image_path = Rails.root.to_s + “/public/upload_images/reactnative”
FileUtils.mkdir_p(image_path) unless FileTest.exist?(image_path)
pp “************** params *******************”
pp params
cnt = 1
while true do
break if params[“file_” + cnt.to_s].blank?
file = params[“file_” + cnt.to_s]
fname = file.original_filename
File.open(image_path + “/#{fname}”, ‘wb’) { |f|
f.write(file.read)
}
cnt += 1
end
end
[/bash]
全ソース
以下に全ソースを貼り付けておきます。
[bash]
import React from “react”
import {
StyleSheet,
Text,
View,
ScrollView,
Image,
CameraRoll,
Alert,
TouchableHighlight,
Button,
} from “react-native”
import axios from “axios”
class App extends React.Component {
constructor(props){
super(props)
this.state = {images: [], imageSel: [], selPhoto: “”}
}
componentDidMount() {
let svThis = this
CameraRoll.getPhotos({first:25})
.then(function(obj){
console.log(obj)
svThis.storeImages(obj.edges, svThis)
})
}
storeImages(edges,svThis) {
const images = edges.map((asset) => {
//Alert.alert(asset.node.image.uri)
return asset.node.image
})
let imgSel = []
images.map((img) => {
imgSel.push({uri: img.uri, selected: false})
})
svThis.setState({images: images, imageSel: imgSel})
}
logImageError(err) {
console.log(err)
}
handleClick(img) {
let imgSel = this.state.imageSel.map((sel) => {
if (sel.uri == img.uri){
sel.selected = !sel.selected
}
return sel
})
this.setState({imageSel: imgSel, selPhoto: img.uri})
}
handleUpload(){
let data = new FormData()
let cnt = 1
this.state.imageSel.map((sel) => {
if (sel.selected){
data.append(“file_” + cnt, {uri: sel.uri ,name: “photo_” + cnt + “.jpg”,type:”image/jpg”})
cnt += 1
}
})
let REQ_URI = “http://192.168.11.3:3000/upload_image_from_native”
axios.post(REQ_URI,data)
.then(function(res){
Alert.alert(“good”)
})
.catch(function(err){
console.log(err)
})
}
render() {
let imgs = []
imgs = this.state.images.map((img) => {
let selTrue = false
let selView = null
this.state.imageSel.map((sel) => {
if (sel.uri == img.uri && sel.selected == true){
selTrue = true
}
})
if (selTrue){
selView = (
)
}
return (
this.handleClick(img)}>
{selView}
)
})
return (
{this.state.selPhoto}
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: ‘#F5FCFF’,
},
imageGrid: {
flex: 1,
flexDirection: ‘row’,
flexWrap: ‘wrap’,
justifyContent: ‘center’
},
image: {
width: 100,
height: 100,
margin: 10,
},
imageSel: {
position: “absolute”,
top: 15,
left: 15,
},
check: {
height: 20,
width: 20,
}
})
export default App
[/bash]
Leave a comment