简体   繁体   中英

.NET Api Lambda Proxy Integration Api Gateway S3 File Download Corruption

After uploading a file to S3 (.xlsx in this particular case) the downloaded file is corrupted, it's size is larger than the uploaded file and the resulting.xlsx is corrupted and cannot be opened.

Looking at an identical issue (but for a different file type) a solution was mentioned here https://stackoverflow.com/a/54448752/21119546 but in my case it is not working.

API Gateway has the Binary setting for this file type (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet):

API Gateway Console

Lambda Entry Point is updated to encode as Base64:

protected override void Init(IWebHostBuilder builder)
{
    RegisterResponseContentEncodingForContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ResponseContentEncoding.Base64);
    builder.UseStartup<Startup>();
}

Code for retrieving the file from S3:

public async Task<GetObjectResponse> DownloadFileAsS3ObjectAsync(string fileObjectKey, string bucketName)
{
    var getObjectRequest = new GetObjectRequest
    {
        BucketName = bucketName,
        Key = fileObjectKey
    };
    var response = await _iAmazonS3.GetObjectAsync(getObjectRequest);
    if (response.HttpStatusCode == HttpStatusCode.OK)
    {
        return response;
    }
    throw new FileNotFoundException($"The document '{fileObjectKey}' is not found");
}

Code for the api controller:

[HttpGet]
[ProducesResponseType(typeof(File), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)]
[SwaggerOperation(OperationId = "DownloadFile")]
public async Task<IActionResult> DownloadFileAsync([FromQuery] string fileObjectKey)
{
    _logger.LogInformation("Downloading file {File} from Bucket {BucketName}", fileObjectKey,
        _configuration["IngestionBucketName"]);
    try
    {
        var file = await _s3Client.DownloadFileAsS3ObjectAsync(fileObjectKey, _configuration["IngestionBucketName"]);

        return File(file.ResponseStream, file.Headers.ContentType, fileObjectKey.Split("/").Last());
    }
    catch (FileNotFoundException fne)
    {
        _logger.LogCritical("Error downloading file: {Error}", fne.Message);
        return NotFound();
    }
}

Response from API Gateway:

content-disposition: attachment;filename=XXXXX.xlsx; filename*=UTF-8''XXXXX.xlsx
content-length: **29248**
content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
date: Tue, 31 Jan 2023 16:35:33 GMT
x-amz-apigw-id: fnd1YGPsDoEFqkg=
x-amzn-remapped-content-length: **21934**

Hopefully somebody else had the same issue and i have overlooked something...

Solution for this was simple - the client of the API just needs to set the proper Accept header (in this case the application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) as stated in the API Gateway documentation around binary content handling (the Accept must match the Binary Type defined otherwise it will be ignored and returned using the default Base64 encoding)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM