Flutter - Uploading Image to Firebase Storage - firebase

I am trying to create an admin application that can select and upload an image to the Firebase storage and after that, I want the image URL to automatically reflect in the document that is sending data to the client-side application.
The only problem with this is that I only know how to upload an image to Firebase storage from the admin application. I haven't figured a way, as to how can I get the image URL into my document in Cloud Firestore.
Any suggestions or direction regarding this will be helpful.
I am using the flutter framework.
Database structure :
SkinTreatment :
"SkinTreatment": {
"someDocumentName": {
"title": "Threading",
"packageDetails":"This package will provide you with normal upper EyeBrow Threading",
"price" : "200"
"duration": "75mins"
},
"someDocumentName2": { ... },
"someDocumentName3": { ... }
}

You can certainly write code to write the path and/or URL of a file in Cloud Storage to any database. If you have a StorageReference object representing a file that was uploaded, you can use its getPath() method to get a path to the file in storage, and you can use getDownloadUrl() to asynchronously get a download URL as well.
For help writing data to Firestore, there is plenty of documentation.

Related

Firebase admin upload PayloadTooLargeError: request entity too large

I am using Firebase admin to upload a 250MB video file to cloud storage.
Heres my code:
await bucket.upload(downloadVideoResponse.filePath, { destination, resumable: false })
This code throws the error:
PayloadTooLargeError: request entity too large
How do I remove the file size upload limit? I've look at Firebase storage rules but I do not have any rules imposing a file size limit.
This hints at an upload limit for non resumable files:
https://cloud.google.com/storage/docs/uploads-downloads#size
The answer is simply as follows:
await bucket.upload(downloadVideoResponse.filePath, { destination, resumable: true })
Which seems to remove the file size limit.

Send firebase storage authorization as url parameter from a flutter web app

I would like to know how to make an authorized request to firebase storage using the user Id Token as a parameter in the url. Right now with a firebase rule of 'request.auth != null' I receive a 403 network error (Failed to load video: You do not have permission to access the requested resource). Here is my GET request url:
https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<folder_name>%2F<video_name>.mp4?alt=media&auth=eyJh...<ID TOKEN>...Ll2un8ng
-WITHOUT the firebase rule in place I'm able to successfully get the asset with this request url https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<folder_name>%2F<video_name>.mp4?alt=media
-also tried token=, token_id=, tokenId=
-the reason for not using the firebase SDK to fetch the file is so that I can use the flutter video_player (https://pub.dev/packages/video_player#-example-tab-) package and use this with files in firebase, I mention this in case theres a better way to use the video_player library in flutter web right now:
_controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
closedCaptionFile: _loadCaptions(),
);
[EDIT] It appears that it's not possible to pass the auth in as a query parameter. After some exploring, I found an acceptable way to still use the video_player with your firebase assets that are protected (If you're not using rules to protect them, you can directly use the firebase url). I will post some general steps here and some sample code:
Use the Storage Firebase SDK package to get the Uint8List, the uri given by getDownloadURL has the correct header auth, for example
import 'package:firebase/firebase.dart';
final url = await storagePath.getDownloadURL();
final response = await http.get(url);
if (response.statusCode == 200) {
return response.bodyBytes;
}
use the Uint8List buffer to init a Blob object which you'll use to then create an ObjectURL which basically gives you the same interface as a file url to use as the network url for your video player
final blob = html.Blob([data.buffer], 'video/mp4');
final videoUrl = html.Url.createObjectUrl(blob);
videoPlayerController = VideoPlayerController.network(
videoUrl)
..initialize().then((_) {...
That's it.
Firebase Storage REST does not (rightly) support authorization from GET query string as you are trying to do. Instead, it uses the standard Authorization header (see here).
Firebase cloud storage internally uses Google Cloud Storage. Mentioned here
If the library you use doesn't support HTTP headers yet, you must consider an alternative. The issue you mentioned in the comment shows that the feature is still under development, so you can also wait for the library to come out with the support for headers.
Internally all this package does for flutter-web is create an HtmlElementView widget here for which it passes a VideoElement (ref here) from the package dart:html with the provided URL which translates to a <Video> tag inside a shadow dom element in your web page. The error 403 could also mean you are trying to access it from a different origin.
I would suggest following approach.
Check your console for any CORS related errors. If yes, then you will have to whitelist your ip/domain in the firebase storage. Check this post for possible approach and more details here.
Check if you are able to access the URL directly with the authorization token as a query parameter as you suggested. If not then, it is not the correct way to access the object and should be corrected. You could update the question with the exact error details.

Uploading by firebase storage

I tried to uplad (multi photos) using firebase storage (site) and it upladed successfully but I can NOT find it in database section anywhere and also it do not appear in application.
How can I upload multi photos by firebase site and appear on database section and also my application?
Thank you
Firebase storage and realtime database are two different entities, so after uploading image to firebase storage you need to save the download url in realtime database on your own, at path of your choice, in the following example, images url are being saved at images path
var uploadTask = storageRef.child('images/rivers.jpg').put(file);
uploadTask.on('state_changed', function(snapshot){
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
}, function(error) {
// error uploading file
}, function() {
// File uploaded successfully, now store the download url in realtime database
uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
console.log('File available at', downloadURL);
firebase.database().ref('images').set({
image:downloadURL
});
});
});
before saving images url in realtime database make sure you have enabled realtime database for your project
You can't save photos directly in the realtime-database. After you upload the photos get the URLs and save them in the realtime-database.

google cloud vision api quickstart error opening file

I am following the following Google Cloud Vision quickstart:
https://cloud.google.com/vision/docs/quickstart
This is using the API Explorer, and I get
Error Opening File
I have created a bucket named vision2018, and checked Share Publicly for the file.
My portion of the request related to the file is:
"image":
{
"source":
{
"imageUri":"gs://vision2018/demo-image.jpg"
}
}
The response I get is:
{
"responses": [
{
"error": {
"code": 5,
"message": "Error opening file: gs://vision2018/demo-image.jpg\"."
}
}
]
}
}
What do I need to specify in order to access files in my GCP storage?
Alternatively, I read other Stack Overflows that talk about GOOGLE_APPLICATION_CREDENTIALS, Simple API Key, and "Create Service account key and download the key in JSON format", ... but these seem to be giving commands in the shell, which this quickstart doesn't even open.
Is there initial setup assumed prior to the quickstart?
I am not ready to call the api from code
You might want to doublecheck your request. I went to the quickstart, replaced the placeholder imageUri with gs://vision2018/demo-image.jpg and it worked just fine. The error message you posted is what would be displayed if you had given gs://vision2018/demo-image.jpg\" instead.
Regarding the second part of your question: these are authentication methods. In this particular case, under Authentication you will find a drop down which lets you chose between API key and Google OAuth 2.0. If you chose the former, you don't need to do anything as a demo key will be used just for the purposes of the quickstart. If you chose OAuth 2.0, a popup will appear prompting you to authenticate with a google account. All in all, what you need to do is follow step-by-step the instructions given by the quickstart.
I was receiving a similar JSON response from the Google Vision API:
"error": {
"code": 7,
"message": "Error opening file: gs://bucket/file.jpg."
}
The fix was to set the GCS file's permission to public-read:
gsutil acl set public-read gs://bucket/file.jpg
Finally I investigated what happened. The problem is that your API token is only grant for process the image (allow right to use OCR engine), but that API is not also for accessing object in GS.
Therefore "message": "Error opening file:
The problem is similar with this post:Authorize Google Cloud Vision API to Google Storage image Maybe the error message is a bit dumb than many years ago.
The solution also mentioned in the answer section, but if you want some thing more clear (expose security side-effect) here it is: Set GCS read-only public
Reason I want to keep using API because it's better for use it in mobile application, we cannot give the OAuth2.0 to any phone. However, still find a way to secure the read-public bucket.

Download a file from AWS S3 with Angular 2+

I have an ASP.NET Core web app and I'm using Angular 4. There are a lot of resources showing how to upload a file to S3, which I've done. But there doesn't seem to be anything about reading the file.
I want to give users the ability to upload a JSON file, save it to S3, then on a different view show the user all of the files they've uploaded as well as display the content of the file.
Are there any resources for showing how to do this?
If its publicaly available items, you can use the S3 JavaScript SDKs 'getObject' method to download a file.
/* The following example retrieves an object for an S3 bucket. */
var params = {
Bucket: "examplebucket",
Key: "HappyFace.jpg"
};
s3.getObject(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
AcceptRanges: "bytes",
ContentLength: 3191,
ContentType: "image/jpeg",
ETag: "\"6805f2cfc46c0f04559748bb039d69ae\"",
LastModified: <Date Representation>,
Metadata: {
},
TagCount: 2,
VersionId: "null"
}
*/
});
If the files are private, use S3 Signed Urls or CloudFront Signed Urls( or Cookies) to generate a download Url from your backend after authorizing the user. Using this download url, download the file from S3 directly in angular app.
Examples:
Using CloudFront signed urls.
Using S3 Signed Url using the S3 SDKs getSignedUrl method.
Another option is to generate S3 temporary access credentials from AWS STS directly from your backend and send back to the Angular app or using a authentication service such as AWS Cognito so that Angular app can use it to invoke the S3 SDK.

Resources