Open AlbertoPotter opened 5 years ago
Thanks! You can try this method。
import RNFetchBlob from 'rn-fetch-blob';
import RNFS from 'react-native-fs';
import { Alert, Platform, CameraRoll } from 'react-native';
export default function (base64Img, success, fail) {
const dirs = Platform.OS === 'ios' ? RNFS.LibraryDirectoryPath : RNFS.ExternalDirectoryPath; // 外部文件,共享目录的绝对路径(仅限android)
const downloadDest = `${dirs}/${((Math.random() * 10000000) | 0)}.png`;
const imageDatas = base64Img.split('data:image/png;base64,');
const imageData = imageDatas[1];
RNFetchBlob.fs.writeFile(downloadDest, imageData, 'base64').then((rst) => {
// console.log('writeFile',downloadDest)
try {
CameraRoll.saveToCameraRoll(downloadDest).then((e1) => {
console.log('suc',e1)
success && success()
}).catch((e2) => {
console.log('fai',e2)
Alert.alert('没有读写权限。请在[设置]-[应用权限]-[实验助手]开启')
})
} catch (e3) {
// Alert.alert(JSON.stringify(e3))
console.log('catch',e3)
fail && fail()
}
});
}
Hey @YanYuanFE , thank you for your response.
I'll make sure to close this issue once I had implemented this solution and give detailed information on how I did it.
Keep hacking!.
Hi @YanYuanFE,
I've been trying to get this working with Expo (managed flow) but I'm stuck. I need to be able to turn the base64 data into a blob so that I can upload it with AWS AppSync. If I could save the image away as a file, that would be fine too, but every way I've tried seems not to work
rn-fetch-blob
because there's an error where it says DocumentDir isn't defined (this is a known issue it seems), so the approach above isn't available unless I eject my Expo app.null
(it works OK for actual urls):
export const urlToBlob = (url: string): Promise<Blob> => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onerror = reject;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve(xhr.response);
}
};
xhr.open('GET', url);
xhr.responseType = 'blob'; // convert type
xhr.send();
});
};
fetch
, but it just gives an error:
const response = await fetch(b64Data);
const blob = await response.blob();
// Error is TypeError: Network request failed at XMLHttpRequest.xhr.onerror (whatwg-fetch.js:504) at XMLHttpRequest.dispatchEvent (event-target.js:172) at XMLHttpRequest.setReadyState (XMLHttpRequest.js:580) at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:394)
* I've tried creating the byteArray like this, but I get an error :
```typescript
export function dataURItoBlob(dataURI: string) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
const byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
const ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
const ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
return new Blob([ab], { type: mimeString });
}
// Error is
Error: Creating blobs from 'ArrayBuffer' and 'ArrayBufferView' are not supported
await FileSystem.writeAsStringAsync(uri, b64Data, {encoding: 'base64'});
, I wasn't really expecting this to work, and I get
Unable to upload document: {
"framesToPop": 1,
"nativeStackAndroid": [
{
"methodName": "decode",
"lineNumber": 161,
"file": "Base64.java"
},
{
"methodName": "decode",
"lineNumber": 136,
"file": "Base64.java"
},
{
"methodName": "decode",
"lineNumber": 118,
"file": "Base64.java"
},
{
"methodName": "writeAsStringAsync",
"lineNumber": 280,
"file": "FileSystemModule.java"
},
{
"methodName": "invoke",
"lineNumber": -2,
"file": "Method.java"
},
{
"methodName": "invokeExportedMethod",
"lineNumber": 97,
"file": "ExportedModule.java"
},
{
"methodName": "callMethod",
"lineNumber": 117,
"file": "NativeModulesProxy.java"
},
{
"methodName": "invoke",
"lineNumber": -2,
"file": "Method.java"
},
{
"methodName": "invoke",
"lineNumber": 372,
"file": "JavaMethodWrapper.java"
},
{
"methodName": "invoke",
"lineNumber": 158,
"file": "JavaModuleWrapper.java"
}
],
"userInfo": null,
"code": "E_UNKNOWN_ERROR"
}
I've spent 2 days trying to find a work-around for something that seems so simple. Have you any ideas how I can get a blob
or save the image to a file?
Thanks!!
Hi @isocra , Thank you for your attention。 You can try this library instead of rn-fetch-blob for expo.
Hi, with Expo SDK38, I've found a way of doing this. In the handleSignature
method that gets the signature as base64, I use
const newFileUri = `${FileSystem.documentDirectory}${Date.now()}.jpg`;
const dataPart = signature.split(',', 2);
await FileSystem.writeAsStringAsync(newFileUri, dataPart[1], {encoding: FileSystem.EncodingType.Base64});
Hi YanYuan!
I´m building an app that requires a signature functionality and your component is just great.
Though in your README I can´t find an example where you save the signature to the gallery, and because I´m new in React Native I haven´t been able to implement a hack that lets me save the signature.
Thanks in advanced!