AndroidのReactNativeアプリでbase64画像の保存とPOST送信をします。
画像の保存
iOSでの保存、もしくはAndroidでhttp or httpsリソースの画像の保存(base64だとエラー)の場合
まずはbase64でない場合。
以下で画像のダウンロードができます。
一度FileSystemに画像をダウンロードして、そのURIを使っています。
DowloadImage.jsx
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import * as Permissions from 'expo-permissions';
const downloadImage=( file )=>{
FileSystem.downloadAsync(
file.uri,
FileSystem.documentDirectory + 'image.jpeg'
)
.then( async ( { uri } ) => {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL );
if( status !== 'granted' ) return
CameraRoll.saveToCameraRoll( uri, "photo" );
MediaLibrary.saveToLibraryAsync( uri )
})
}
Androidでbase64画像の保存の場合
Androidで、FileSystemでbase64画像を読み込むと、URLスキームがhttpかhttpsじゃないとダメですって怒られます。
ので、以下で保存します。
DowloadBase64Image.jsx
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import * as Permissions from 'expo-permissions';
const downloadImage=( file )=>{
const dataUri = file.uri
const tempFileDirectory = `${ FileSystem.cacheDirectory }uploadTmp`
// 一時保存用のディレクトリを作る
await FileSystem.makeDirectoryAsync( tempFileDirectory, { intermediates: true } )
// 一時保存用のファイルを作る
const tempFilePath = `${ tempFileDirectory }${ Date.now() }.jpeg`
// データの中身を取り出す
const base64EncodedData = dataUri.split( ',' )[ 1 ]
// base64として、作ったファイルに書き込む
await FileSystem.writeAsStringAsync( tempFilePath, base64EncodedData, {
encoding: FileSystem.EncodingType.Base64,
} )
// そのファイルのパスをURIに、同様にカメラロールに保存
const uri = tempFilePath
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL );
if( status !== 'granted' ) return
CameraRoll.saveToCameraRoll( uri, "photo" );
MediaLibrary.saveToLibraryAsync( uri )
// 一時的に作っていただけなので、ファイルを消す
await FileSystem.deleteAsync( tempFilePath )
}
Androidだと、ReactNativeのライブラリではFileSystemにそのままbase64はダウンロードできないので、自分でファイル作って書き込んで、それのURIを使っています。
POST送信
AndroidでAxiosを使って、base64画像を送信しようとすると、Network Errorが出ます。
これも、以下で送信可能です(ほぼ上記の保存と同じ)。
PostBase64Image.jsx
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import * as Permissions from 'expo-permissions';
import axios from 'axios'
const postImage=( file )=>{
// 画像の保存と同様にFileSystemにファイルを作って書き込む
const dataUri = file.uri
const tempFileDirectory = `${ FileSystem.cacheDirectory }uploadTmp`
toryAsync( tempFileDirectory, { intermediates: true } )
const tempFilePath = `${ tempFileDirectory }${ Date.now() }.jpeg`
const base64EncodedData = dataUri.split( ',' )[ 1 ]
await FileSystem.writeAsStringAsync( tempFilePath, base64EncodedData, {
encoding: FileSystem.EncodingType.Base64,
} )
const uri = tempFilePath
// そのファイルのパスを、送るファイルのURIに指定
const file = {
uri:uri,
type: "image/jpeg",
name: "file.jpeg",
}
const formData = new FormData()
formData.append( "file", file )
await axios.post( URL, data)
.then( async () =>{
// 一時的に作っていただけなので、ファイルを消す
await FileSystem.deleteAsync( tempFilePath )
})
}