Rafael Zasas
Rafael Zasas

Reputation: 993

How to GetDownloadURL with Go Firebase Admin SDK

I have a web server and need to allow admins to upload images and users to view images.

I am able to upload the file just fine with this:

    bucket, err := client.DefaultBucket()
    if err != nil {
        return "", fmt.Errorf("client.DefaultBucket: %v", err)
    }

    fileName := fmt.Sprintf("%v/%v", bucketName, object)

    // Upload an object with storage.Writer.
    wc := bucket.Object(fileName).NewWriter(ctx)
    wc.ChunkSize = 0 // note retries are not supported for chunk size 0.

    if _, err = io.Copy(wc, buf); err != nil {
        return "", fmt.Errorf("io.Copy: %v", err)
    }
    // Data can continue to be added to the file until the writer is closed.
    if err := wc.Close(); err != nil {
        return "", fmt.Errorf("Writer.Close: %v", err)
    }

But getting a downloadable URL is a different story.

I found this to work with the emulators suite:

    url := wc.Attrs().MediaLink

However, in production, I get a 401 error when opening the link in the browser, and I get broken images when using them as src url's in my html responses.

I understand that there is the ability to get SignedURL's that last for a short period of time. This is impractical and is completely a non starter. My server cant afford to GetSignedURL's for hundreds of images on every page load.

My frontend is javascript free and so using the client javascript SDK is also not an option.

The goal is to upload the images, get a download url, and save the download url's in the database alongside the other data.

Is this possible to do using the Golang Firebase Admin SDK?

Upvotes: 0

Views: 304

Answers (2)

Sanjuwa
Sanjuwa

Reputation: 43

Try this way, What I tried is creating the key using go the uuid pacakge and adding to metadata as @Frank stated in above answer.

bucket, err := client.DefaultBucket()
if err != nil {
    return "", fmt.Errorf("client.DefaultBucket: %v", err)
}

fileName := fmt.Sprintf("%v/%v", bucketName, object)

// Upload an object with storage.Writer.
wc := bucket.Object(fileName).NewWriter(ctx)
wc.ChunkSize = 0 // note retries are not supported for chunk size 0.

wc.ObjectAttrs.Metadata = map[string]string{
    "firebaseStorageDownloadTokens": key,
}

if _, err = io.Copy(wc, buf); err != nil {
    return "", fmt.Errorf("io.Copy: %v", err)
}
// Data can continue to be added to the file until the writer is closed.
if err := wc.Close(); err != nil {
    return "", fmt.Errorf("Writer.Close: %v", err)
}

And getting the MediaLink appending the token as query parameter to it

url := wc.Attrs().MediaLink + "&token=" + key

Upvotes: 0

Frank van Puffelen
Frank van Puffelen

Reputation: 599876

Since this functionality is not built into the Go Admin SDK for Firebase, you options are the same as in this answer for the Node.js SDK: Get Download URL from file uploaded with Cloud Functions for Firebase.

So you'll have to set a metadata/metadata/firebaseStorageDownloadTokens nested property on the object with the token value you want to use in the download URL. While this is not a documented solution, it has worked for many years now and, last I checked, there are no plans to remove this.

Of course if you feel like making this functionality available to others too, a PR on the Go Admin SDK would almost certainly be welcomed.

Upvotes: 0

Related Questions