Expo 图像选择器 uri 不适用于每个 phone
Expo image picker uri does not work on every phone
我正在使用 Expo 构建 React Native 应用程序。我希望用户能够保存个人资料图片。我已经尝试了几个月了。我使用 Expo 图像选择器来执行此操作。但是,我取回的文件在本地系统中。当我尝试登录另一个 phone 时,图像没有显示,可能是因为它仅限于从中获取图像的 phone。我在 iOS 上阅读了一篇关于删除 file:// 的文章,但无论如何它都不起作用。在后端,我使用的是 GraphQL,我只是将 photoUrl 作为字符串存储在 MongoDB 数据库中。我的意思是,那里有很多 React Native 应用程序,因此必须有一个简单的解决方案。
代码:
useEffect(() => {
(async () => {
if (Platform.OS !== 'web') {
const {
status,
} = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert(
'Vi behöver din profilbild för att göra det lättare för andra användare att veta vem du är'
);
}
}
})();
}, []);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.cancelled && Platform.OS === 'ios') {
const photo = result?.uri.replace('file://', '/private');
setPhotoUrl(photo);
}
};
您正在为上传方法设置本地图像 uri,因此当您尝试取回它时无法取回,因为您上传到 db 的 uri 是本地 uri。
您必须使用 blob 存储并配置您的后端...
步骤:
- 从本地 uri 获取文件名
- 将图像上传到 blob 存储
- 在你的数据库中将 blob url 保存为 'string'(例如:https://yourblobstorage/profilepicture/filename.png)
- 最好的办法是将文件名更改为用户 ID 或某种唯一 ID。
- 所以每次你从你的 blob 中为这个用户获取这个url
- 更改个人资料图片你也这样做(所以用户个人资料图片名称始终是他的用户ID,这对你来说很简单并且节省了一些space XD)
我的实现:
图像选择器方法:
const addCameraImage = async () => {
setOverlayVisible(false)
const { granted } = await ImagePicker.requestCameraPermissionsAsync()
if (granted === true) {
let image = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
})
await uploadImage(image)
} else {
setPermissionOverlayVisible(true)
}
}
上传图片方法:
const uploadImage = async (image: ImagePicker.ImagePickerResult) => {
if (image.cancelled === false) {
setLocalImage(image.uri)
const filename = image.uri.split('/').pop();
const file = new ReactNativeFile({
uri: image.uri,
name: filename,
type: `image/${filename.split('.').pop()}`
});
try {
await updateProfilePictureMutation({
variables: {
id: data?.user?.id,
profilePicture: file
},
update: (cache, { data }) => {
try {
const getUserByIdCachedData = cache.readQuery<GetUserByIdQuery>({ query: GetUserByIdDocument, variables: { id: userId } })
if (!getUserByIdCachedData) return
const newData = {
...getUserByIdCachedData,
user: {
...getUserByIdCachedData.user,
profilePicture: data.updateUser.profilePicture
}
}
cache.writeQuery({ query: GetUserByIdDocument, variables: { id: userId }, data: newData })
} catch (e) {
console.error(e)
}
}
})
} catch (e) {
}
setLocalImage(null)
}
}
打开一个模式,询问用户是否允许打开设置以启用权限,如果他们之前已经拒绝并尝试拍照:
const openSettings = () => {
if (Platform.OS === 'ios') {
Linking.openURL('app-settings:')
setPermissionOverlayVisible(false)
}
if (Platform.OS === 'android') {
const pkg = Constants.manifest.releaseChannel ? Constants.manifest.android.package : 'host.exp.exponent'
IntentLauncher.startActivityAsync(
IntentLauncher.ACTION_APPLICATION_DETAILS_SETTINGS,
{ data: 'package:' + pkg }
)
setPermissionOverlayVisible(false)
}
}
现在这里我一拍完就设置本地图片,这样他们就不用等你把图片上传到blob了,一旦上传了,我就从blob中获取
const getAvatarImage = () => {
if (updateProfilePictureLoading) return null
if (localImage) {
return { uri: localImage }
}
if (data?.user?.profilePicture) {
return { uri: data?.user?.profilePicture }
}
return null
}
我希望这能帮助你多了解一点,我一直在纠结这个问题,但后来我意识到它很简单。
我还在后端对我的上传和从 blob 获取进行了突变和查询。
干杯。
我正在使用 Expo 构建 React Native 应用程序。我希望用户能够保存个人资料图片。我已经尝试了几个月了。我使用 Expo 图像选择器来执行此操作。但是,我取回的文件在本地系统中。当我尝试登录另一个 phone 时,图像没有显示,可能是因为它仅限于从中获取图像的 phone。我在 iOS 上阅读了一篇关于删除 file:// 的文章,但无论如何它都不起作用。在后端,我使用的是 GraphQL,我只是将 photoUrl 作为字符串存储在 MongoDB 数据库中。我的意思是,那里有很多 React Native 应用程序,因此必须有一个简单的解决方案。
代码:
useEffect(() => {
(async () => {
if (Platform.OS !== 'web') {
const {
status,
} = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert(
'Vi behöver din profilbild för att göra det lättare för andra användare att veta vem du är'
);
}
}
})();
}, []);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.cancelled && Platform.OS === 'ios') {
const photo = result?.uri.replace('file://', '/private');
setPhotoUrl(photo);
}
};
您正在为上传方法设置本地图像 uri,因此当您尝试取回它时无法取回,因为您上传到 db 的 uri 是本地 uri。
您必须使用 blob 存储并配置您的后端...
步骤:
- 从本地 uri 获取文件名
- 将图像上传到 blob 存储
- 在你的数据库中将 blob url 保存为 'string'(例如:https://yourblobstorage/profilepicture/filename.png)
- 最好的办法是将文件名更改为用户 ID 或某种唯一 ID。
- 所以每次你从你的 blob 中为这个用户获取这个url
- 更改个人资料图片你也这样做(所以用户个人资料图片名称始终是他的用户ID,这对你来说很简单并且节省了一些space XD)
我的实现:
图像选择器方法:
const addCameraImage = async () => {
setOverlayVisible(false)
const { granted } = await ImagePicker.requestCameraPermissionsAsync()
if (granted === true) {
let image = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 1,
})
await uploadImage(image)
} else {
setPermissionOverlayVisible(true)
}
}
上传图片方法:
const uploadImage = async (image: ImagePicker.ImagePickerResult) => {
if (image.cancelled === false) {
setLocalImage(image.uri)
const filename = image.uri.split('/').pop();
const file = new ReactNativeFile({
uri: image.uri,
name: filename,
type: `image/${filename.split('.').pop()}`
});
try {
await updateProfilePictureMutation({
variables: {
id: data?.user?.id,
profilePicture: file
},
update: (cache, { data }) => {
try {
const getUserByIdCachedData = cache.readQuery<GetUserByIdQuery>({ query: GetUserByIdDocument, variables: { id: userId } })
if (!getUserByIdCachedData) return
const newData = {
...getUserByIdCachedData,
user: {
...getUserByIdCachedData.user,
profilePicture: data.updateUser.profilePicture
}
}
cache.writeQuery({ query: GetUserByIdDocument, variables: { id: userId }, data: newData })
} catch (e) {
console.error(e)
}
}
})
} catch (e) {
}
setLocalImage(null)
}
}
打开一个模式,询问用户是否允许打开设置以启用权限,如果他们之前已经拒绝并尝试拍照:
const openSettings = () => {
if (Platform.OS === 'ios') {
Linking.openURL('app-settings:')
setPermissionOverlayVisible(false)
}
if (Platform.OS === 'android') {
const pkg = Constants.manifest.releaseChannel ? Constants.manifest.android.package : 'host.exp.exponent'
IntentLauncher.startActivityAsync(
IntentLauncher.ACTION_APPLICATION_DETAILS_SETTINGS,
{ data: 'package:' + pkg }
)
setPermissionOverlayVisible(false)
}
}
现在这里我一拍完就设置本地图片,这样他们就不用等你把图片上传到blob了,一旦上传了,我就从blob中获取
const getAvatarImage = () => {
if (updateProfilePictureLoading) return null
if (localImage) {
return { uri: localImage }
}
if (data?.user?.profilePicture) {
return { uri: data?.user?.profilePicture }
}
return null
}
我希望这能帮助你多了解一点,我一直在纠结这个问题,但后来我意识到它很简单。
我还在后端对我的上传和从 blob 获取进行了突变和查询。
干杯。