The React Native 0.70 app uses react-native-blob-util
to read jpg image file from image picker before uploading it to OSS. Here is the code:
import ReactNativeBlobUtil from "react-native-blob-util"; //v0.19
const fileData = await ReactNativeBlobUtil.fs.readFile(filePath, 'base64'); //filePath is the file path from image picker
const fileData1 = `data:image/jpeg;base64,${fileData}`
The fileData1
was uploaded with fetch
:
const response = await fetch(preSignedUrl, {. //preSignedUrl is acquired from backend node server
method: 'PUT',
headers: { 'Content-Type': 'image/jpeg' },
body: fileData1,
})
The image uploaded can't be open. The md5(fileData1) before fetch PUT
is the same as the md5 returned from OSS. It may be related to the jpg file format on OSS but not sure where is the issue.
UPDATE:
return of await fetch(filePath)
(fetch fileData1 throws error):
LOG responsefetch in uploadTOOSS: {"_bodyBlob": {"_data": {"__collector": [Object], "blobId": "44313295-9de3-4dfe-b9be-bbdef6110f4b", "lastModified": 0, "name": "rn_image_picker_lib_temp_9373b67e-6f10-4932-b743-f2155da4fca8.jpg", "offset": 0, "size": 47367, "type": "image/jpeg"}}, "_bodyInit": {"_data": {"__collector": [Object], "blobId": "44313295-9de3-4dfe-b9be-bbdef6110f4b", "lastModified": 0, "name": "rn_image_picker_lib_temp_9373b67e-6f10-4932-b743-f2155da4fca8.jpg", "offset": 0, "size": 47367, "type": "image/jpeg"}}, "bodyUsed": false, "headers": {"map": {"content-type": "image/jpeg"}}, "ok": false, "status": 0, "statusText": "", "type": "default", "url": ""}
You are uploading the base64-encoded image data directly to the OSS (Object Storage Service) using a pre-signed URL.
When you encode the file content in base64 and prepend the data URL schema (
data:image/jpeg;base64
), it is suitable for embedding images directly into web pages or CSS files (see "How to display Base64 images in HTML?" for instance).However, for uploading to OSS, you should convert the base64 back to binary data because the storage expects the raw binary format of the image, not its base64-encoded representation.
So you need to convert the base64-encoded string back to binary before uploading. That can be done using the
Blob
orBuffer
API, but since you are working in a React Native environment, you will have to rely on what is available there. Unfortunately, React Native does not have the same globalBlob
constructor as web browsers, butreact-native-blob-util
provides a workaround.You need to make sure
base64ToBlob
correctly converts the base64 string to a binary format thatfetch
can handle. Ifreact-native-blob-util
does not directly supportbase64ToBlob
, you might have to usefetch
to create a blob from the base64 string, like:Since
ReactNativeBlobUtil.base64ToBlob
does not exist, and that thefetch(fileData1)
approach results in a network error, you might consider instead to manually converting the base64 string to binary data, and then upload this binary data usingfetch
.Try and create a function to convert the base64 string to a binary format that
fetch
can handle as binary data, using theUint8Array
:That would manually convert the base64-encoded string to a binary format (
Uint8Array
) that is then uploaded.It is a bit lower level and circumvents the need for a
Blob
, which should be a good fit considering the capabilities and limitations of React Native's environment.The
atob
function used in the conversion process is a built-in JavaScript function that decodes a base64-encoded string. However, it might not be available in all React Native environments. Ifatob
is not available in your React Native environment, you might need to use a polyfill or an alternative method to decode the base64 string. Libraries such asreact-native-blob-util
might offer similar functionality, or you can use a third-party library to decode base64 strings.The OP reports in the comments making it work: