AWS S3 File Download from the client-side - javascript

I am currently trying to download the file from the s3 bucket using a button from the front-end. How is it possible to do this? I don't have any idea on how to start this thing. I have tried researching and researching, but no luck -- all I have searched are about UPLOADING files to the s3 bucket but not DOWNLOADING files. Thanks in advance.
NOTE: I am applying it to ReactJS (Frontend) and NodeJS (Backend) and also, the file is uploaded using Webmerge
UPDATE: I am trying to generate a download link with this (Tried node even if I'm not a backend dev) (lol)
see images below
what I have tried so far
onClick function

If the file you are trying to download is not public then you have to create a signed url to get that file.
The solution is here Javascript to download a file from amazon s3 bucket?
for getting non public files, which revolves around creating a lambda function that will generate a signed url for you then use that url to download the file on button click
BUT if the file you are trying to download you is public then you don't need a signed url, you just need to know the path to the file, the urls are structured like: https://s3.amazonaws.com/ [file path]/[filename]
They is also aws amplify its created and maintain by AWS team.
Just follow Get started and downloading the file from your react app is simply as:
Storage.get('hello.png', {expires: 60})
.then(result => console.log(result))
.catch(err => console.log(err));

Here is my solution:
let downloadImage = url => {
let urlArray = url.split("/")
let bucket = urlArray[3]
let key = `${urlArray[4]}/${urlArray[5]}`
let s3 = new AWS.S3({ params: { Bucket: bucket }})
let params = {Bucket: bucket, Key: key}
s3.getObject(params, (err, data) => {
let blob=new Blob([data.Body], {type: data.ContentType});
let link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=url;
link.click();
})
}
The url in the argument refers to the url of the S3 file.
Just put this in the onClick method of your button. You will also need the AWS SDK

Related

Trying to get a stream link of a video file from GDRIVE API

I'm trying to get a stream link for my video files to stream it on my web app from google drive api, but its not working properly. I have double checked the docs for any errors in syntax and i can't seem to find any.
for context here is my code:
`
drive.files.get({fileId: myfileId,alt: 'media'},{responseType: 'stream'}, (err, res) => {
if (err) return console.log(`The API returned an error: ${err}`);
console.log(res)
});
`
I'm getting a passthrough object in res.data field and its giving an error of "Unknown output format: 'media' ". The file i'm trying to stream is a .mp4 file.
I have also double checked my authentication and its working fine because i was able to retrieve my folder id and file id using the api.
Am i doing anything wrong here? Any help would be appreciated.
THANKS.
Once you have authenticated the client library, you can use the following code to get a stream link for a video file stored in Google Drive
// Replace fileId with the ID of the video file you want to stream
const fileId = '1234567890';
// Get the file from Google Drive
const file = await drive.files.get({ fileId, alt: 'media' });
// Get the stream link for the file
const streamLink = file.data;

Is it possible upload file with metadata by storage nestJS sdk?

I am using Azure storage and Nestjs. I am using Azure storage to store some static files. I can upload files by Nestjs storage SDK successfully.Now I need to upload a file with some custom blob metadata, I have go through the source code of Nestjs storage SDK, but seems there is no predefined way to do this. So is it possible to upload blobs with custom metadata? Or is there any workarounds?
Thanks!
I also have reviewed the source code of azureStorageService, it not provides useful methods. But the upload operation replys a storageUrl with SAS token, we could use it to make another HTTP request: set-blob-metaData to set blob metadata. This is my test code,name is the metadata in my test:
#Post('azure/upload')
#UseInterceptors(
AzureStorageFileInterceptor('file', null),
)
async UploadedFilesUsingInterceptor(
#UploadedFile()
file: UploadedFileMetadata,
) {
file = {
...file,
buffer : Buffer.from('file'),
originalname: 'somename.txt'
};
const storageUrl = await this.azureStorage.upload(file);
//call rest api to set metadata
await this.httpService.put(storageUrl + "&comp=metadata",null,{headers:{'x-ms-meta-name':'orginal name here'}})
.subscribe((response) => {
console.log(response.status);
});
{
Logger.log(storageUrl);
}}
}
Result:

How can I upload files to google drive that are in a url?

I try to upload a photo that I have in a URL on another server, but it does not work for me or I do not know how to upload them in this case I am going to upload a photo but I also want to upload files that will upload to that URL.
const img = await fetch("http://example.com/api/photo")
await gapi.client.drive.files.create({
resource: {
name: "New Folder",
body: img,
}
})
The simple anwser is you cant do it like that. The file being Uploaded must be sent in the form of a stream
Download the file to your own machine and then upload it from there. Or try to figure out how to turn your url into a stream.
var fileMetadata = {
'name': 'photo.jpg'
};
var media = {
mimeType: 'image/jpeg',
body: fs.createReadStream('files/photo.jpg')
};
drive.files.create({
resource: fileMetadata,
media: media,
fields: 'id'
}, function (err, file) {
if (err) {
// Handle error
console.error(err);
} else {
console.log('File Id: ', file.id);
}
});
I believe your goal as follows.
You want to download an image data from an URL, and want to upload the downloaded image data to Google Drive.
From your script, the image data is downloaded by const img = await fetch("http://example.com/api/photo").
You want to achieve this using googleapis for Javascript.
Modification points:
In this case, it retrieves Blob of image data from fetch, and the blob is uploaded to Google Drive.
Unfortunately, in the current stage, it seems that although googleapis for Javascript can create new file with the metadata, the file content cannot be included. By this, in this answer, I use the method of this thread. The downloaded image data is uploaded using fetch with multipart/form-data.
When above poiints are reflected to your script, it becomes as follows.
Modified script:
const img = await fetch("http://example.com/api/photo").then((e) => e.blob());
const fileMetadata = {name: "sampleName"}; // Please set filename.
const form = new FormData();
form.append('metadata', new Blob([JSON.stringify(fileMetadata)], {type: 'application/json'}));
form.append('file', img);
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', {
method: 'POST',
headers: new Headers({'Authorization': 'Bearer ' + gapi.auth.getToken().access_token}),
body: form
}).then(res => res.json()).then(res => console.log(res));
By this modification, the downloaded image data is uploaded to Google Drive with multipart/form-data.
Note:
In this modification, it supposes as follows.
Your URL of http://example.com/api/photo is the direct link of the image data.
Your authorization script can be used for uploading a file to Google Drive.
In this answer, as a sample script, the file is uploaded with uploadType=multipart. In this case, the maximum file size is 5 MB. Please be careful this. When you want to upload the file with the large size, please check the resumable upload. Ref
References:
Google API Client Library for JavaScript
Using Fetch
Files: create
Upload file data
Related question
How I can upload file to google drive with google drive api?

res.download file from Amazon S3

I am trying to download a file from outside of my root directory however every time I try, it tries to take it from the root directory. I will need the user of my site to be able to download these files.
The file has initially been uploaded to Amazon S3 and I have accessed it using the getObject function.
Here is my code:
app.get('/test_script_api', function(req, res){
var fileName = req.query.File;
s3.getObject(
{ Bucket: "bucket-name", Key: fileName },
function(error, s3data){
if(error != null){
console.log("Failed to retrieve an object: " + error);
}else{
//I have tried passing the S3 data but it asks for a string
res.download(s3data.Body);
//So I have tried just passing the file name & an absolute path
res.download(fileName);
}
}
);
});
This returns the following error:
Error: ENOENT: no such file or directory, stat '/home/ec2-user/environment/test2.txt'
When I enter an absolute path it just appends this onto the end of /home/ec2-user/environment/
How can I change the directory res.download is trying to download from?
Is there an easier way to download your files from Amazon S3?
Any help would be much appreciated here!
I had the same problem and I found this answer:
NodeJS How do I Download a file to disk from an aws s3 bucket?
Based on that, you need to use createReadStream() and pipe().
R here more about stream.pipe() - https://nodejs.org/en/knowledge/advanced/streams/how-to-use-stream-pipe/
res.attachment() will set the headers for you.
-> https://expressjs.com/en/api.html#res.attachment.
This code should work for you (based on the answer in the above link):
app.get('/test_script_api', function (req, res) {
var fileName = req.query.File;
res.attachment(fileName);
var file = s3.getObject({
Bucket: "bucket-name",
Key: fileName
}).createReadStream()
.on("error", error => {
});
file.pipe(res);
});
In my case, on the client side, I used
This made sure that the file is downloading.

How does one specify directory, permissions, and create sub-directory for S3 in AWS lambda code?

I am implementing an AWS lambda function
(JavaScript, node.js environment)
which uses a call which goes like this:
const aws = require('aws-sdk');
const s3 = new aws.S3();
function work1(obj, cb_Work1) {
console.log(">>> Calling work");
s3.putObject({
Bucket: bucketName,
Key: 'test.txt',
Body: JSON.stringify(obj)
})
.promise()
.then(() => {
console.log('S3 -> UPLOAD SUCCESS');
work2(obj, (resp) => {
cb_Work1(resp);
});
})
.catch(e => {
console.log('S3 -> UPLOAD ERROR');
console.log(e);
cb_Work1({
error: e
});
});
}
So here Key seems to be the file name.
But the thing is that I don't find yet detailed docs for s3.putObject so I don't know
1) how to specify a directory name (not just bucket name),
2) how to define permissions on that file which I am creating
3) how to create a sub-directory before putting the file, etc., etc., etc.
How can these things be done via aws-sdk (from JavaScript, node.js code)?
Many thanks in advance.
As stated in the S3 documentation here:
The Amazon S3 console treats all objects that have a forward slash "/" character as the last (trailing) character in the key name as a folder, for example examplekeyname/. You cannot upload an object with a key name with a trailing "/" character by using the Amazon S3 console. However, objects named with a trailing "/" can be uploaded with the Amazon S3 API by using the AWS CLI, the AWS SDKs, or REST API.
As for permissions, the API provides the putObjectAcl function that allows defining an ACL to use when putting the object.

Categories

Resources