Reputation: 5044
I'm successfully creating a signed download url using the UrlSigner
class provided by the .NET SDKs for Cloud Storage. I'm on Google.Cloud.Storage.V1
3.5.0.
What I'm trying to do now is have that url download the file not as the file key as it is in the bucket, but as a user friendly string.
From my understanding this needs to be done with the Content-Disposition
header. Here is my code currently:
var contentDispositionQueryParam = new KeyValuePair<string, IEnumerable<string>>(
"Content-Disposition", new[] { $"attachment; filename={fileInfo.CustomerFileName}" });
var requestTemplate = UrlSigner.RequestTemplate
.FromBucket(_cloudStorageBucketName)
.WithObjectName(fileInfo.FileKey)
.WithHttpMethod(HttpMethod.Get)
.WithQueryParameters(new []{contentDispositionQueryParam});
var options = UrlSigner.Options.FromDuration(TimeSpan.FromMilliseconds(_urlExpirationTimeMs));
preSignedUrl.Url = await _objectUrlSigner.GetSignedUrlAsync(requestTemplate, options, token);
This unfortunately is not working. The url generated has no reference to this query param so it feels like it's being filtered out somewhere along the way. Is this an invalid value? I also tried response-content-disposition
with no luck.
I was basing my assumption off of this here - https://cloud.google.com/storage/docs/xml-api/reference-headers#contentdisposition and other pieces of documentation for how to send query params, but there really isn't a clear example of how to do this that I can find.
I have seen examples where we update the Content-Disposition
metadata of the uploaded file but for various reasons this will not work for me.
EDIT for clarity:
This is how I tried using response-content-disposition
Same setup as above except:
var contentDispositionQueryParam = new KeyValuePair<string, IEnumerable<string>>(
"response-content-disposition", new[] { HttpUtility.UrlEncode($"attachment; filename={fileInfo.CustomerFileName}") });
I'm basing my usage of this off the documentation here - https://cloud.google.com/storage/docs/xml-api/reference-headers#responsecontentdisposition
Upvotes: 0
Views: 177
Reputation: 5044
I got this sorted eventually. It doesn't help that for about 12 hours I was putting my changes in the wrong method so my code was never called, but either way here is my final solution:
var contentDispositionQueryParam = new Dictionary<string, IEnumerable<string>>
{
{
"response-content-disposition", new List<string>
{
$"attachment; filename=\"{fileName}\""
}
}
};
var requestTemplate = UrlSigner.RequestTemplate
.FromBucket(_cloudStorageBucketName)
.WithObjectName(fileKey)
.WithHttpMethod(HttpMethod.Get)
.WithQueryParameters(contentDispositionQueryParam);
var options = UrlSigner.Options.FromDuration(TimeSpan.FromMilliseconds(_urlExpirationTimeMs));
signedUrl = await _objectUrlSigner.GetSignedUrlAsync(requestTemplate, options, token);
This does not work if you url encode the query param value yourself or if you do not include the double quotes around your desired file name, so just be careful with those things.
Upvotes: 1