image picker path for stripe readfilesync Flutter Web - flutter

I'm using the file_picker package for flutter https://pub.dev/packages/file_picker
I have read many times that because you can’t access paths on web browsers, you need to use the bytes property, e.g.
FilePickerResult result = await FilePicker.platform.pickFiles();
if(result != null) {
var path = print(result.files.single.path); // this will return null
var bytes = print(result.files.singe.bytes); // this will return a Uint8List of bytes
} else {
// User canceled the picker
}
But I have to upload the images my users select from their devices via the web (so for all types of devices) to my Stripe Connect API in order for them to have a validated identity_document when they register. The bytes Uint8List will throw an error from firebase, here is my code:
export const uploadIdentityFront = async (uid: any, identityFront: any) => {
const fp = fs.readFileSync(identityFront);
const frontIdentity = await stripe.files.create({
file: {
data: fp,
name: 'identityFront.jpg',
type: 'application/octet-stream',
},
purpose: 'identity_document',
});
await updateId(uid, { frontIdentityFileId: frontIdentity.id })
return frontIdentity;
}
The error thrown:
[firebase_functions/unknown] TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received an instance of Array
I will need to send stripe an image document via the file system's readFileSync property in order to do this, but with Flutter Web not being able to print the path for the image chosen by the user, I am stuck on how to resolve this issue

I use this code to send bytes to my server, which uses stream to send. You can use http package to send streams.
var request = http.MultipartRequest(
'POST',
Uri.parse('_url'),
);
request.files.add(
http.MultipartFile.fromBytes(
'identityFront', //name of field which you receive in api
bytes, // bytes
filename: 'identityFront.jpg', // optional name
//contentType: content, optional media Type
));
request.fields.addEntries([
MapEntry('uid', 'uid_value_in_String_Type'),
]);
await request.send();

I finally solved it. For anyone trying to upload a file to Stripe via flutter web, don't create a fs.readFileSync in your backend server side code. Instead, remove it and upload a file like this:
export const uploadIdentityFront = async (uid: any, identityFront: any) => {
const frontIdentity = await stripe.files.create({
file: {
data: identityFront,
name: 'identityFront.jpg',
type: 'image/jpg',
},
purpose: 'identity_document',
});
await updateId(uid, { frontIdentityFileId: frontIdentity.id })
return frontIdentity;
}
This way, you can upload the file via the file_picker package and uploading it as a picker.file.first.bytes. But don't wrap it in a string - send it just like this as a callable function in firebase functions:
await uploadFrontPassport.call(
<dynamic, dynamic>{'identityFront':picked.files.first.bytes}
);

Related

Flutter send signature image to GCP bucket but file is not usable

I am trying to send a signature from flutter to a GCP Storage bucket.
Currently, I can send a file to the bucket but it's not openable.
Here is what I am using to get base64 format which I supposed is the intended format to send files.
final data = await _signaturePadKey.currentState!
.toImage(pixelRatio: 3.0);
final image = await data.toByteData(
format: ui.ImageByteFormat.png);
// To send
final base64String =
base64.encode(image!.buffer.asUint8List());
setState(() => {_signatureFile = base64String});
Then I am sending my request as :
Future postOKTrackingSignature(String signature, String projectID) async {
await refreshSTSToken(projectID);
String token = await getSTSToken();
// Headers
var headersData = {
"Authorization": "Bearer $token",
"Content-Type": "image/png"
};
// URL building
var resourcePart =
"XXX";
var paramsData = {
'uploadType': 'multipart',
'name': "${resourcePart}signature.png",
};
var baseURI = 'https://storage.googleapis.com/upload/storage/v1/b/';
String bucketName = "XXX";
var query = paramsData.entries.map((p) => '${p.key}=${p.value}').join('&');
// Body
var bodyData = signature;
final response = await http.post(
Uri.parse("$baseURI$bucketName/o?$resourcePart$query"),
headers: headersData,
body: bodyData);
switch (response.statusCode) {
case 200:
print("$baseURI$bucketName/o?$resourcePart$query");
return {"statusCode": response.statusCode};
default:
print("$baseURI$bucketName/o?$resourcePart$query");
return {"statusCode": response.statusCode, "error": response.body};
}
}
Sadly, I the file got upload but is not usable when I want to get preview, or even download it and try to open it. But while I change the extension to .txt, take the string to : https://base64.guru/converter/decode/file it show me my image a png.
I also tried this :
var dataPrepation = base64.normalize(signature);
var bodyData = "data:image/png;base64,$dataPrepation";
String example :
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
Consider Firebase Storage instead of base64; this stackoverflow topic compares the two and outlines the benefits of each.
In light of this, I strongly advise you to continue working on your project utilizing Firebase Storage.
Now, to Upload a file to Cloud Storage, you first create a reference to the full path of the file, including the file name.
// Create a storage reference from our app
final storageRef = FirebaseStorage.instance.ref();
// Create a reference to "mountains.jpg"
final mountainsRef = storageRef.child("mountains.jpg");
// Create a reference to 'images/mountains.jpg'
final mountainImagesRef = storageRef.child("images/mountains.jpg");
// While the file names are the same, the references point to different files
assert(mountainsRef.name == mountainImagesRef.name);
assert(mountainsRef.fullPath != mountainImagesRef.fullPath);
Additionally, I would suggest you review the guide for Firebase Cloud Storage in Flutter written by Dane Mackier.

Upload Blob Url to Firebase Storage | Flutter

So I already read about the topic but I simply didn't understand the solutions on stack.
I came up with this code:
Im saving a url looking like this:
final String myDataUrl = file.url;
print(myDataUrl);
blob:http://localhost:51947/2952a3b1-db6a-4882-a42a-8e1bf0a0ad73
& then Im trying to add it into Firebase Storage with the putString operator, that I guessed that suited me best while reading the Documentation. I thought that I have a Url and therefore should be able to upload it like this:
FirebaseStorage.instance
.ref()
.child("bla")
.putString(myDataUrl, format: PutStringFormat.dataUrl);
But it doesn't work, it says that:
Error: Invalid argument (uri): Scheme must be 'data': Instance of '_Uri'
So Im guessing that it somehow can't format my url to one that is accepted.
What can I do different to upload a blob successfully to firebase Storage?
-----------------Answer----------------------
Answer in the comment of the answer.
You have to convert your Blob to a Uint8List & upload it like:
Future<Uint8List> fileConverter() async {
final reader = html.FileReader();
reader.readAsArrayBuffer(file!);
await reader.onLoad.first;
return reader.result as Uint8List;
}
and then put it into your Storage:
Future uploadFile(String uid) async {
if (file == null) return;
final path = "nachweise/$uid";
Uint8List fileConverted = await fileConverter();
try {
FirebaseStorage.instance
.ref()
.child(path)
.putData(fileConverted)
.then((bla) => print("sucess"));
} on FirebaseException catch (e) {
return null;
}
}
The Firebase Storage SDKs can upload local data as either a File, an array of bytes, or a base-64 encoded string. The only URLs it accepts are so-called data URLs, which start with data:// and contain the complete data of the object. They cannot upload data directly from URLs that you more commonly see, such as http:// or https://.
You'll need to first download the data from that URL to the local device, and then upload it from there.

Flutter - Unhandled Exception: NoSuchMethodError: The getter 'filename' was called on null

I am still learning flutter and have been facing problems in my project like the error stated in the title. I want to upload files in flutter using dio and formData. The img[] is the variable from the database in mongodb and I am having an error whenever the user passes null image. (Because we do not require the user to send an image.)
Here's my code.
upload2(List<File> babyList) async {
var formData = FormData.fromMap({
"userId": _id,
"babyname": _baby,
});
if(_babyList.length != 0){
for (int i = 0; i < _babyList.length; i++) {
var fileName = babyList[i].path.split('/').last;
formData.files.addAll([
MapEntry(
"babyimage[]",
await MultipartFile.fromFile(babyList[i].path,
filename: fileName,
contentType: new MediaType(lookupMimeType(fileName).split('/')[0], lookupMimeType(fileName).split('/')[1],
))),
]);
}
} else {
formData.files.addAll([ MapEntry("babyimage[]", null)]);
}
// sending the formdata to the database
AuthService().requestorRegister(formData).then((val) async {
print('Form Submitted Successfully');
_confirmationDialog(context);
});
}
Okay, I have tried not to add babyimage[] in the formdata, I have also tried to put empty array, null and babyList as value. The thing is they work and the only problem in my case is the server. The server wasn't updated. So sometimes we gotta check the server too. lol
PS. I removed the else in the code since it is empty.

How to pass ACL properties to flutter amplify while uploading file to S3?

Or How to upload an image to s3 with public access by Flutter Amplify?
In my current flutter project, I can't pass ACL:public-read property while uploading files to S3 using amplify.
And because of this, whenever I'm uploading a new file to s3, I need to make it public manually.
So I just want to upload a new file with public read access for everyone.
I found some solutions for the Javascript project but not in the Flutter project.
Below is a method, I'm using to upload.
Future<String> uploadFile(String fileName, File local) async {
try {
Map<String, String> metadata = <String, String>{};
metadata['name'] = 'filename';
metadata['desc'] = 'A file';
S3UploadFileOptions options = S3UploadFileOptions(accessLevel: StorageAccessLevel.guest, metadata: metadata);
UploadFileResult result = await Amplify.Storage.uploadFile(key: fileName, local: local, options: options);
return result.key;
} catch (e) {
print('UploadFile Err: ' + e.toString());
}
return null;
}
I think you should be using Dio for declaring the client object that will be used for posting the request
You can find an example code in the following answer
So far Flutter Amplify is not giving any option to upload images with public access.
It always uploads with private read access.
So I updated a few things in my project as described below.
Before Amplify integration I was uploading images to S3 and storing that URL to my server, and wherever I have to display, I'm just fetching URL from my server and loading images.
But now I'm storing key(that is used to upload images to S3 by Amplify) to my server.
And to display the image I'm getting the image URL from Amplify using that key(which is stored in my server).
Amplify adds a token to the image URL with a default validity of 7 days
Future<String> getUrl(String key) async {
try {
S3GetUrlOptions options = S3GetUrlOptions(accessLevel: StorageAccessLevel.guest, expires: 10000);
GetUrlResult result = await Amplify.Storage.getUrl(key: key, options: options);
String url = result.url;
return url;
} catch (e) {
print('GetUrl Err: ' + e.toString());
}
return null;
}
So it can be displayed by ImageView.

Unable to format file to upload to Cloudinary

I am trying to send an image from Flutter application to Cloudinary using Uploading with a direct call to the REST API,but getting this error:
{"error":{"message":"Invalid file parameter. Make sure your file parameter does not include '[]'"}}
I tried to encode image as an array of bytes, base64Encode but none of that worked, I followed this documentation.
Does anybody know how to encode the file so I can send it?
thanks
EDIT:
#override
Future<void> getImageSignature(File image) async {
return await _callWithExceptionWrap(() async {
if (image != null) {
DateTime dateTime = DateTime.now();
String url = _formatUrlForUploadSignature();
Dio dio = NetworkUtils.createDioConnection();
debugPrint('REQUEST TO SERVER');
Response serverResponse = await dio.post(url, data: {
"paramsToSign": {
'public_id': 'public_id_654',
"timestamp": dateTime.millisecondsSinceEpoch,
"upload_preset": "signed_preset",
"source": "uw",
}
});
debugPrint('REQUEST TO CLOUDINARY');
String signature = serverResponse.data['signature'];
List<int> bytes = image.readAsBytesSync();
var base64Image = base64Encode(bytes);
Map<String, dynamic> map = {
'api_key': _CLOUDINARY_API_KEY,
'public_id': 'public_id_654',
'signature': signature,
'source': 'uw',
'timestamp': dateTime.millisecondsSinceEpoch,
'upload_preset': 'signed_preset',
'file': base64Image,
};
debugPrint('json : ${map}');
// FormData formData = new FormData.fromMap(map);
Response cloudinaryResponse = await dio.post(_CLOUDINARY_URL, data: map);
debugPrint('*************************** Cloudinary response : ${cloudinaryResponse.data}');
}
});
The signature is ok, since I am not getting 401 error(signature I am receiving from the server.
here is the cloudinary url:
_CLOUDINARY_URL = 'https://api.cloudinary.com/v1_1//image/upload';
That is not correct api to use on a public client (Mobile app), you shouldn't be exposing your API_KEY and API_SECRET. Check out this package instead, which uses the correct api to upload files https://pub.dev/packages/cloudinary_public
The package Olajide suggested would only work for Unsigned uploads. For anyone that wants to use Signed uploads use this package https://pub.dev/packages/cloudinary_sdk