Wondering if someone knows how to upload an image from flutter (not really relevant, javascript would be the same problem) but set the image path/name from the server side.
When I upload my image to my s3 bucket in AWS amplify, the name the client passes is taken to be put in the bucket.
I would like to change this behavior by passing the image in the api call but then on the server set the path and name.
Has anyone had any luck doing this?
Best regards
I'm assuming you have already gone through the official documentation on uploading via flutter client which looks something like this.
final UploadFileResult result = await Amplify.Storage.uploadFile(
local: exampleFile,
key: 'ExampleKey',
onProgress: (progress) {
print('Fraction completed: ${progress.getFractionCompleted()}');
}
);
here, you can change key to anything of your choice e.g.
key: 'folder1/image1.jpg'
If this is not what you want to do then you can always create a new REST endpoint on your server which accepts multipart/form-data. nodejs/express example
Simple file upload to S3 using aws-sdk and Node/Express
Related
Problem:
I need to be able to remove all link decoration from the download URL that is generated for images in Firebase Storage.
However, when all link decoration is stripped away, the resulting link currently would return a JSON document of the image's metadata.
Context:
The flow goes as follows:
An image is uploaded to Firebase from an iOS app. Once that is done the download URL is then sent in a POST request to an external server.
The server that the URL is being sent to doesn't accept link decoration when submitting image URLs.
Goal:
Alter the Firebase Storage download URL such as it is stripped of all link decoration like so:
https://firebasestorage.googleapis.com/v0/b/example.appspot.com/o/[FOLDER_NAME]%[IMAGE_NAME].jpg
Notes:
The problem is twofold really, first the link needs to be manipulated to remove all the link decoration. Then the behavior of the link needs to changed, since in order to return an image, you need ?alt=media following the file extension, in this case .jpg. Currently, without link decoration, using the link with my desired structure would return a JSON document of the metadata.
The current link structure is as follows:
https://firebasestorage.googleapis.com/v0/b/example.appspot.com/o/[FOLDER_NAME]%[IMAGE_NAME].jpg?alt=media&token=[TOKEN]
Desired link structure:
https://firebasestorage.googleapis.com/v0/b/example.appspot.com/o/[FOLDER_NAME]%[IMAGE_NAME].jpg
The token is necessary for accessing the image depending security rules in place, but can be ignored with the proper read permissions. I can adjust the rules as needed, but I still need to be able to remove the ?alt=media and still return an image.
Building up on Frank's answer, if you access to your associated Google Cloud Platform project, find the bucket in the Storage tab and make this bucket public, you will be able to get the image from here with the format you wish. That is, you will not be accessing through Firebase
https://firebasestorage.googleapis.com/v0/b/example.appspot.com/o/[FOLDER_NAME]%[IMAGE_NAME].jpg
but through Google Cloud Storage, with a link like
https://storage.googleapis.com/[bucket_name]/[path_to_image]
Once in your GCP project Console, access the Storage bucket with the same name as the one you have in your Firebase project. They are the same bucket. Then make the bucket public by following these steps. After that, you will be able to construct your links as mentioned above and they will be accessible with no token and no alt=media param. If you do not want to make the public to everyone, you will be able to play around with the permissions there as you wish.
You could split the url string into two halves by using String.componentsSeparatedByString(_ separator:)
Storage.storage().reference().child(filePath).downloadURL(completion: { (url, error) in
let urlString = url.absoluteString
let urlStringWithoutQueryString = urlString.componentsSeparatedByString("?").first!
})
Calling .downloadURL on a StorageReference will return you that URL, but this method can be used to remove the query string from any URL. String.componentsSeparatedByString(_ separator:) breaks a String into an array of Strings, splitting the string by any occurrence of a given separator, in this case ?.
NOTE this method assumes that ? occurs only once within the url string, which I believe is the case for all Firebase Storage urls.
You should treat the download URL that you get back from Firebase as an opaque string. There's no way to strip the parameters from a download URL without breaking that download URL.
If you want to allow public access to the files in your bucket with simpler URLs, consider making the object in your (or even your entire) bucket public.
I'm working in an Asp.Net Core 2 web api for files hosted at Google Cloud Storage. The files hosted there are not public, so I can't use the MediaLink property of the object. I tried to make a download endpoint using MemoryStream but when there are many users downloading large files at once I run into memory issues.
My question is: is there a way to create something link a one-time download link for a file or something similar?
I'm also trying to implement what's described in this link but I'd need to give the bearer token to the user. I can't do that.
Any tips?
Yes. Google Cloud Storage offers a feature called "signed URLs" that is what you described: a URL that is only good for a short while to download a single file. The idea is that you craft a download URL, then use the private key of a service account to "sign" the URL. Anyone holding that final URL can use it to act as that service account for the purpose of downloading that one object.
Take a look: https://cloud.google.com/storage/docs/access-control/#Signed-URLs
Writing code to generate the signed URL is a bit tricky, but the client libraries provide helper methods in several languages to do it for you. You can also generate one with the gsutil command: gsutil signurl -d 10m privatekey.p12 gs://bucket/foo
There is a code sample for generating he signed URLs programatically on their GitHub project: Signed URLs
I managed to Create it using C#. I'm posting here because this will be useful to someone else:
1 - Create your private key
2 - Create and UrlSigner:
private readonly UrlSigner _urlSigner;
2 - In your class constructor:
using (var stream = File.OpenRead(_googleSettings.StorageAuthJson))
{
_urlSigner = UrlSigner.FromServiceAccountData(stream);
}
_googleSettings.StorageAuthJson has the physical path of the json file you downloaded when creating your key.
3 - Method to get the URL:
public string GetSignedUrl(string bucketName, string objectName, TimeSpan duration) {
var url = _urlSigner.Sign(bucketName, objectName, duration, null);
return url;
}
The messenger Send API gives me back the response
(#546) The type of file you're trying to attach isn't allowed. Please try again with a different format. error code: 546, error_subcode: 154502
However, if I host the same exact image on Google Cloud instead of Amazon S3, then the image sends fine.
My link to the AWS image:
https://s3.amazonaws.com/paloma-staging-public/files/conversation-step-56-80925.gif
My link to the google cloud image:
https://storage.googleapis.com/callparty/thumbsup.gif
are there any special reasons that a link to an image stored on S3 would not work as an image attachment, but a link to an image stored on google cloud would work?
The answer was that for the AWS link the ContentType of the file was not set.
While uploading to S3 I had to manually set the ContentType of the file appropriately ("image/gif", "image/png" etc.) and for the google cloud storage this must have been automatically set.
This is why the S3 link causes an auto-download, and the google cloud link displays the image in the browser.
I've been using Filepicker.IO in order to upload files directly from the browser to the amazon s3 and most things are working fine, the only problem i'm facing now is that after the upload is done, i'm not getting the name of the file in the s3.
Filepicker js api is returning this object:
Object {url: "https://www.filepicker.io/api/file/xxxxxxxxxxxxx", filename: "xyzhi.mp4", mimetype: "video/mp4", size: 36735, isWriteable: true}
Usually this object comes with a property named 'key' which has the name of the file in the S3.
This happens when the upload is not done from the local computer, if i pick a local file everything works ok, but if i pick a file from any of the providers (e.g Dropbox, Google Drive), i can't get the filename in the S3 server.
Thanks.
You should make sure that you are using a function that is explicitly storing to S3, for instance filepicker.pickAndStore or filepicker.store. As noted in the filepicker.io pick API documentation, the "key" parameter on fpfiles returned specifically from the .pick() call are deprecated and not meant to be used.
If I'm using GWT File widget and form panel, can someone explain how to handle upload on blobstore on google application engine??
Take a look at gwtupload. There are examples on how to use it with GAE Blobstore.
Google blobstore is specifically designed to upload and serve blobs via http. Blobstore service (obtained using BlobstoreServiceFactory.getBlobstoreService()) generates http post action for you to use in the html form. By posting file to it you upload your blob to the blobstore. When you generate this action you provide a path to the handler (servlet) where you have access to uploaded blob key:
Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(req);
BlobKey blobKey = blobs.get("data");
Note, that "data" is the file field in your form. All you have is a key to the blob (your file). From here you take control - you can save this key for later and/or immediately serve the blob on a page (using key):
BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
blobstoreService.serve(blobKey, res);
Of course, for details see Google documentation.
One nice feature of the blobstore that it's integrated with Google Mapper (rudimentary map-reduce) service (work in progress) which lets you process files uploaded as blobs line by line: http://ikaisays.com/2010/08/