We have a requirement to upload files/attachments on CASE record (using custom drag and drop section) from Service Cloud to AWS S3. We ran into file size limit issue with files bigger than 12 MB. Since the upload process is asynchronous process, it goes through for files of size up-to 12 MB and we are OK with that. But, we are unable to download files which are bigger than 6 MB (synchronous call). Reason for downloading the files instead of using full context URL to AWS is, it's a client/browser call and exposes Secret key information. Please advise if there is a way to download files up-to 12 MB (atleast) via server call from Apex. All we know and have is AWS host URL, Bucket Name, Secret Key and Access Key. Any help is greatly appreciated!
This is demonstrated in the Amazon Toolkit. AWS allows you to create a pre-signed URL that does not expose your secret key. You can leverage this to upload and download files from S3 without exposing your secrets client-side. You'll want to read the manual for specifics. Here's the description from the documentation:
A pre-signed URL gives you access to the object identified in the URL, provided that the creator of the pre-signed URL has permissions to access that object. That is, if you receive a pre-signed URL to upload an object, you can upload the object only if the creator of the pre-signed URL has the necessary permissions to upload that object.
All objects and buckets by default are private. The pre-signed URLs are useful if you want your user/customer to be able upload a specific object to your bucket, but you don't require them to have AWS security credentials or permissions. When you create a pre-signed URL, you must provide your security credentials, specify a bucket name, an object key, an HTTP method (PUT for uploading objects), and an expiration date and time. The pre-signed URLs are valid only for the specified duration.
You can generate a pre-signed URL programmatically using the AWS SDK for Java or the AWS SDK for .NET. If you are using Visual Studio, you can also use AWS Explorer to generate a pre-signed object URL without writing any code. Anyone who receives a valid pre-signed URL can then programmatically upload an object.
You can also choose to upload file parts, which basically goes like this: StartMultipartUpload, UploadParts, FinishMultipartUpload. I haven't gotten this working in Apex Code, as it is pretty tricky to get just right, but it's all there in the documentation.
Finally, you can use the Range header on the GET Object to download parts of the file at a time, and figure out a way to recombine them later. This is also tricky without running into memory limits, but possible with some client-side effort.
Amazon allows you to create signed policies and URLs so you don't expose your secret keys to the client. You can then upload or download straight from the browser without going through Salesforce servers. You can even set a close expiration date on that URL's so the links cannot be shared by users.
The java sample would be the best example for you to get it ported over to Apex.
Referring the Sync Apex call to download more than 6MB file at Salesforce, I would suggest trying post the recordId from Salesforce to AWS and write a script at AWS to call standard Salesforce APIs to upload file to Salesforce from AWS.
Refer below documentation: - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm
I haven't tried this but this should work ideally.