react-native-image-picker+axios 上传失败 Android
react-native-image-picker+axios uploads fail on Android
我有一个应用程序,我使用 react-native-image-picker
拍摄和 select 照片。然后我使用 axios
和 FormData
将 selected 文件上传到我的后端。
这在 iOS 上工作正常,我可以从图像选择器中获取 URL,并将其添加到我的 FormData 和 POST 到服务器。
但是在 Android,当我使用相同的代码时请求停止。当我省略文件并且在我的多部分表单数据中只有文本字段时,它可以 post 。但是当我引用文件时,请求永远不会结束。
向网络服务器添加 CORS 支持没有帮助。将服务器域添加到 network_security_config.xml
也无济于事。如前所述,只要我不向 FormData/
添加任何文件,我就可以 GET 和 POST 到端点
我可以看到从图像选择器返回的我的 URI 是 Android 上的 content://my.app.id.imagepickerprovider/cacheDir/rn_image_picker_lib_temp_76d709ca-3d09-4b20-8ce4-bd8280180141.jpg
样式,这似乎是一个无效路径。
然后我研究了如何将 content://
转换为有效的文件系统路径,并尝试了各种解决方案,在 RNFetchBlob 和 RNFS 中使用 stat()
,其中 none 有效。我还尝试制作自己的自定义模块,但没有用,最后安装了似乎正确转换路径的 react-native-get-real-path
模块。我现在有类似 /data/user/0/my.app.id/cache/rn_image_picker_lib_temp_638f24e9-0974-4fef-b6f0-e0a3873a14e6.jpg
的东西
所以现在,当我制作我的 FormData 时,我添加了一个带有像 file:///data/user/0/my.app.id/cache/.....jpg
这样的 URI 的文件
但这仍然使我的 HTTP 请求挂起,就像我只是传递 content://
URI 一样。
我还尝试使用 react-native-image-picker
的 base64 输出,然后将 data:...
URI 设置为文件表单字段中的 uri,这适用于 iOS(但令人难以置信慢),并且不适用于 Android.
我一定是漏掉了什么 - 有什么提示吗?
在我的组件中:
const imagePickerCallback = useCallback((response: ImagePickerResponse) => {
setCurrentPhoto(response)
}, [])
const handleUpload = useCallback(async () => {
const { uri, base64, fileName, fileSize, type } = currentPhoto
fileUploadStore.add(uri, fileName, type, fileSize)
}, [currentPhoto, fileUploadStore])
我的 FileUploadStore
调用我的 API 尝试使用 URI 并调用 axios。
不同解决方案的结果在评论中(actualUri
)。
async uploadFile(
uri: string,
name: string,
type: string,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
cancelToken?: CancelToken
): Promise<string> {
const formData = new FormData()
// Gives `NETWORK_ERROR` on android - file://content://dk.bosj.app.debug.imagepickerprovider/cacheDir/
const actualUri = Platform.select({ ios: uri, android: `file://${uri}` })
// Gives `NETWORK_ERROR` on android - /data/user/0/dk.bosj.app.debug/cache/rn_image_pi
const actualUri = Platform.select({ ios: uri, android: await RNGRP.getRealPathFromURI(uri) })
// Hangs forever on android - content://dk.bosj.app.debug.imagepickerprovider/cacheDir/
const actualUri = Platform.select({ ios: uri, android: uri })
// Hangs forever on android - file:///data/user/0/dk.bosj.app.debug/cache/rn_image_pi
const actualUri = Platform.select({ ios: uri, android: `file://${await RNGRP.getRealPathFromURI(uri)}` })
formData.append('file', {
uri: actualUri,
name,
type,
})
console.log(JSON.stringify(formData))
formData.append('stuff', 'AAAGNAAAA')
const response = await this.api.post<{ id: string }, null>(BosjEndpoint.FILES, formData, {
onUploadProgress,
cancelToken,
})
if (!response.ok) {
throw new Error(response.problem)
}
if (!response.data || !response.data.id) {
throw new Error('DATA_ERROR')
}
return response.data.id
}
好的,问题与我尝试的解决方案相去甚远。
更新 Android 上的 flipper SDK 版本成功了,现在可以上传文件了!
我从 0.37.0 更新到 0.75.1
https://github.com/facebook/react-native/issues/28551#issuecomment-624347067
我有一个应用程序,我使用 react-native-image-picker
拍摄和 select 照片。然后我使用 axios
和 FormData
将 selected 文件上传到我的后端。
这在 iOS 上工作正常,我可以从图像选择器中获取 URL,并将其添加到我的 FormData 和 POST 到服务器。
但是在 Android,当我使用相同的代码时请求停止。当我省略文件并且在我的多部分表单数据中只有文本字段时,它可以 post 。但是当我引用文件时,请求永远不会结束。
向网络服务器添加 CORS 支持没有帮助。将服务器域添加到 network_security_config.xml
也无济于事。如前所述,只要我不向 FormData/
我可以看到从图像选择器返回的我的 URI 是 Android 上的 content://my.app.id.imagepickerprovider/cacheDir/rn_image_picker_lib_temp_76d709ca-3d09-4b20-8ce4-bd8280180141.jpg
样式,这似乎是一个无效路径。
然后我研究了如何将 content://
转换为有效的文件系统路径,并尝试了各种解决方案,在 RNFetchBlob 和 RNFS 中使用 stat()
,其中 none 有效。我还尝试制作自己的自定义模块,但没有用,最后安装了似乎正确转换路径的 react-native-get-real-path
模块。我现在有类似 /data/user/0/my.app.id/cache/rn_image_picker_lib_temp_638f24e9-0974-4fef-b6f0-e0a3873a14e6.jpg
所以现在,当我制作我的 FormData 时,我添加了一个带有像 file:///data/user/0/my.app.id/cache/.....jpg
但这仍然使我的 HTTP 请求挂起,就像我只是传递 content://
URI 一样。
我还尝试使用 react-native-image-picker
的 base64 输出,然后将 data:...
URI 设置为文件表单字段中的 uri,这适用于 iOS(但令人难以置信慢),并且不适用于 Android.
我一定是漏掉了什么 - 有什么提示吗?
在我的组件中:
const imagePickerCallback = useCallback((response: ImagePickerResponse) => {
setCurrentPhoto(response)
}, [])
const handleUpload = useCallback(async () => {
const { uri, base64, fileName, fileSize, type } = currentPhoto
fileUploadStore.add(uri, fileName, type, fileSize)
}, [currentPhoto, fileUploadStore])
我的 FileUploadStore
调用我的 API 尝试使用 URI 并调用 axios。
不同解决方案的结果在评论中(actualUri
)。
async uploadFile(
uri: string,
name: string,
type: string,
onUploadProgress?: (progressEvent: ProgressEvent) => void,
cancelToken?: CancelToken
): Promise<string> {
const formData = new FormData()
// Gives `NETWORK_ERROR` on android - file://content://dk.bosj.app.debug.imagepickerprovider/cacheDir/
const actualUri = Platform.select({ ios: uri, android: `file://${uri}` })
// Gives `NETWORK_ERROR` on android - /data/user/0/dk.bosj.app.debug/cache/rn_image_pi
const actualUri = Platform.select({ ios: uri, android: await RNGRP.getRealPathFromURI(uri) })
// Hangs forever on android - content://dk.bosj.app.debug.imagepickerprovider/cacheDir/
const actualUri = Platform.select({ ios: uri, android: uri })
// Hangs forever on android - file:///data/user/0/dk.bosj.app.debug/cache/rn_image_pi
const actualUri = Platform.select({ ios: uri, android: `file://${await RNGRP.getRealPathFromURI(uri)}` })
formData.append('file', {
uri: actualUri,
name,
type,
})
console.log(JSON.stringify(formData))
formData.append('stuff', 'AAAGNAAAA')
const response = await this.api.post<{ id: string }, null>(BosjEndpoint.FILES, formData, {
onUploadProgress,
cancelToken,
})
if (!response.ok) {
throw new Error(response.problem)
}
if (!response.data || !response.data.id) {
throw new Error('DATA_ERROR')
}
return response.data.id
}
好的,问题与我尝试的解决方案相去甚远。
更新 Android 上的 flipper SDK 版本成功了,现在可以上传文件了!
我从 0.37.0 更新到 0.75.1
https://github.com/facebook/react-native/issues/28551#issuecomment-624347067