Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getSignedUrl for multiple files #969

Closed
rakyesh22 opened this issue Jan 2, 2020 · 17 comments
Closed

getSignedUrl for multiple files #969

rakyesh22 opened this issue Jan 2, 2020 · 17 comments
Assignees
Labels
api: storage Issues related to the googleapis/nodejs-storage API. external This issue is blocked on a bug with the actual product. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@rakyesh22
Copy link

getSignedUrl works only for single file.
need to work with multiple files, so there is no option to pass and retrieve multiple files signed url.
please suggest the fastest option to create multiple file signedUrl.

@bcoe bcoe added the type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. label Jan 2, 2020
@stephenplusplus
Copy link
Contributor

@rakyesh22 sorry for the trouble, but would you be able to provide more context around what you're trying to do?

@rakyesh22
Copy link
Author

rakyesh22 commented Jan 7, 2020

there is folders in firestore lets say images, excel, json. so now i want to get some files ( a_1.png, a_14.png....a_55.png ) from images folder in single api call. ..
so how can i get all those specified files in single call.
Note: I am using node js as backend language.

@stephenplusplus
Copy link
Contributor

Here's the understanding I'm working from, so let me know if I messed it up: you would like to download multiple files from Firestore into memory, using the @google-cloud/storage module.

so how can i get all those specified files in single call.

I don't believe this is an option that the upstream API offers. You can use bucket.getFiles() to retrieve a reference to multiple File objects, but you would then have to download their contents:

const [files] = await bucket.getFiles({ prefix: 'a_' })
const fileContents = await Promise.all(files.map(file => file.download()))

@rakyesh22
Copy link
Author

rakyesh22 commented Jan 8, 2020

Thanks for answer...
But my concern is with Dont want getting all files with prefix... only want to get specific files URL's .

 const [files] = await bucket.getFiles({ prefix: 'a_' })  

above code will give me All file links
eg. a_1.png, a_2.png, a_3.png, a_4.png.......a_90.png and so on.. ( there might be a 1000 files )

I just want to get Specific Files link.
eg. a_5.png, a_11.png, a_39.png, a_50.png ( so here i want only 4 files Links in single api )

@jkwlui
Copy link
Member

jkwlui commented Jan 13, 2020

I hope I'm understanding your requirements correctly, but it appears you'd like for the client library to generate pre-signed URLs for specific Cloud Storage files with known file names, not directly downloading the file.

If that's the case, you would use file.getSignedUrl() which involves no remote API call:

const fileNames = ['a_5.png', 'a_11.png', ...];
const bucket = storage.bucket('bucket_name');

for (const fileName of fileNames) {
  const [signedUrl] = await bucket.file(fileName).getSignedUrl({
    version: 'v4',
    expires: new Date('2020-12-31T11:59:59'),
    action: 'read'
  });
  console.log(`The signed URL for ${fileName} is ${signedUrl}`);
}

@jkwlui jkwlui added needs more info This issue needs more information from the customer to proceed. type: question Request for information or clarification. Not an issue. and removed type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. labels Jan 13, 2020
@rakyesh22
Copy link
Author

@jkwlui Thanks buddy .
Thats what i am doing currently, using foreach loop to get all files links.
But getting signed url one by one slow downs the executions,

so i am looking for firebase APi/function, where i can pass whole array of file-names and which returns list of all signedUrl .

@bcoe bcoe added external This issue is blocked on a bug with the actual product. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. and removed needs more info This issue needs more information from the customer to proceed. type: question Request for information or clarification. Not an issue. labels Jan 27, 2020
@rakyesh22 rakyesh22 reopened this Jan 30, 2020
@product-auto-label product-auto-label bot added the api: storage Issues related to the googleapis/nodejs-storage API. label Jan 30, 2020
@yogeshs31
Copy link

yogeshs31 commented Feb 19, 2020

Yes I have the same issue for getting multiple files url in one api hit. Please suggest better solution . Because by using foreach loop to get all files links. with signed url one by one slow downs the application,

@sboudouk
Copy link

sboudouk commented Apr 23, 2020

To summarise what people want here I think:

Imagines having images/ path in your Google Cloud Storage bucket. This images path contains like 200 pictures. The bucket is not set to public. And we need our frontend to display all the 200 pictures in an HTML page.

The actual process imply that you have to generate a signedUrl for each of the files present in images/ in your cloud storage. This will slowdown your project a lot, despite where you process this (frontend is the worst, but even backend will slow everything in consequences.)

People are requesting something like bucket.file({prefix : 'images/'} ).getSignedUrl() , that will return an array with signedUrl for every single files in images/.

@stephenplusplus
Copy link
Contributor

@frankyn do you have any thoughts about if and how we would want to support this, or recommend users handle the situation described by @sboudouk? Thanks!

@sboudouk
Copy link

sboudouk commented May 8, 2020

I managed to kind of solve my issue, so I'll explain what I did here maybe it will help peoples there.

Since getSignedUrl for multiple files is slow and restraint you to use loops to do it, I only run one getSignedUrl.

I use the Google Cloud Function availaible in the Google Cloud solutions (https://cloud.google.com/functions?hl=fr), and use the hook when a file is stored to my Cloud Storage. When a file is stored, i use getSignedUrl with the v2 protocole to generate a SignedURL that last for X years (I put like 10 years.), then make a request to my backend to store the SignedURL.

My Google Cloud function looks like this:

const {Storage} = require("@google-cloud/storage");
const axios = require("axios");

exports.saveSignedUrlToMongo = async (event, context) => {
  const gcsEvent = event;                                     // GCS TRIGGERED EVENT.
  console.log(`Processing file: ${gcsEvent.name}`);
  const storage = new Storage();
  const [signedUrl] = await  storage.bucket($YOURBUCKETNAME)       // Generate Signed URL for uploaded file
      .file(`${gcsEvent.name}`).getSignedUrl({
        version: 'v2',                                                        // v2 Allow to set long expire timestamps
        action: 'read',                                                       // Read Only
        expires: Date.now() + 3000000 * 60 * 1000,                            // 6 Years from now
  });

  axios.post($YOURBACKENDURL, {      // Post in document our DB Links
    fileName: gcsEvent.name,
    signedMediaUrl: signedUrl,
    contentType: gcsEvent.contentType,
  }).then(response => {
    console.log(response);
    return 'Ok';
  }).catch(error => {
    console.error('Error in axios request:' + error);
    return error;
  })
};

By doing so, you're only generating SignedURL once, and it is fast. I know it's not the best approach since it's not completly resilient, but that's how I solved my problem now, waiting for a better approach.

@frankyn
Copy link
Member

frankyn commented May 12, 2020

Hi folks, apologies for the delay.

The Cloud Storage API doesn't support a prefix based signed URL to access a group of objects.

At the moment the signing process is going to be slow because each signed URL needs to be signed individually either through IAM API or a local service account private key.

The main solution that I'm aware of is what @jkwlui provided using a foreach. I also do like your solution @sboudouk, but definitely only see two options.

I just noticed that there was a performance improvement released last week with the updated IAM signBlob endpoint https://github.com/googleapis/google-auth-library-nodejs/releases/tag/v6.0.0 in PR: googleapis/google-auth-library-nodejs#908. In https://github.com/googleapis/nodejs-common/releases/tag/v3.1.0. This is being updated when this PR is released: #1157.

The performance issue is for the case that you're signing from a location far away from the West Cost data centers. The new IAM SignBlob API does not have this performance hit and may help improve performance when signing a group of blobs, but it will still take time.

@jkwlui could you help cut the release?

@stephenplusplus
Copy link
Contributor

@frankyn we have released 5.0.0 👍

@frankyn
Copy link
Member

frankyn commented May 14, 2020

Thanks @stephenplusplus! For folks who were seeing a slow turn around time, this may help improve performance as it did for our Java library but don't expect it to be a solution for all.

We may want to close out this issue. I'll forward this feedback to the Cloud Storage team for now, but don't have a turn around time at this time.

Leaving it open in case folks have feedback.

@PierBover
Copy link

There should really be a way to create signed URLs in bulk or be able to create a single URLs that will work for multiple objects.

I have a use case where a user needs to upload hundreds of files. With the current SDK I need to create hundreds of URLs, one by one, or create a signed URL for the whole bucket. Neither of these solutions is optimal.

I could create a bucket just for this upload, and then move the files to the final bucket, but it's a lot of work that should be unnecessary.

@PierBover
Copy link

The gsutil command does support creating signed URLs in bulk... and supports wildcards too. So the functionality is there, but just not on the Node SDK.

Multiple gs:// URLs may be provided and may contain wildcards. A signed URL will be produced for each provided URL, authorized for the specified HTTP method and valid for the given duration.

https://cloud.google.com/storage/docs/gsutil/commands/signurl

@shaffeeullah
Copy link
Contributor

shaffeeullah commented Sep 27, 2022

Hi @PierBover , can you please open a new issue so we can track this request?

@Mihai-github
Copy link

So there's no official option to generate one presingedURL for multiple files?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the googleapis/nodejs-storage API. external This issue is blocked on a bug with the actual product. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

No branches or pull requests

10 participants