function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Aayush MallAayush Mall 

Uploading a CSV file to s3 From Apex

I need to upload a csv file from Apex to a global bucket in s3 and keep the URL.

Below described is my approach for the same using AWS request signing process.
 
public static void uploadCSVFileToS3(String csvFile, String filename, String awsAccessKey, String awsSecretKey, String bucketname){
        try{
            String formattedDateString = Datetime.now().format('EEE, dd MMM yyyy HH:mm:ss');
            String requestType = 'PUT';
            String contentType = 'text/csv';
            String filePath = 'https://s3.amazonaws.com' + '/'+ bucketname + '/' + 'demo.csv';
            
            HttpRequest req = new HttpRequest();
            req.setMethod(requestType);
            req.setHeader('Host','https://s3.amazonaws.com');
            req.setEndpoint(filePath);
            req.setHeader('Content-Length', String.valueOf(csvFile.length()));
            req.setHeader('Content-Type', contentType);
            req.setHeader('Date', formattedDateString);
            req.setHeader('ACL', 'public-read-write');
            Blob CSV = Blob.valueof(csvFile);
            req.setBodyAsBlob(CSV);
            
            String auth = createAuthHeader(requestType, contentType, filename, formattedDateString, bucketname, awsAccessKey, awsSecretKey);
            
            Http http = new Http();
            
            HTTPResponse res = http.send(req);
            System.debug('RESPONSE STRING: ' + res.toString());
            System.debug('RESPONSE STATUS: ' + res.getStatus());
            System.debug('STATUS_CODE: ' + res.getStatusCode());
        } catch(System.CalloutException e) {
            system.debug('AWS Service Callout Exception: ' + e.getMessage());
            system.debug('AWS Service Callout Exception: ' + e.getCause());
            system.debug('Exception: ' + e.getStackTraceString());
        } catch(Exception e) {
            system.debug('Exception: ' + e.getMessage());
            system.debug('Exception: ' + e.getStackTraceString());
        }  
    }

    public static String createAuthHeader(String method, String contentType, String filename, String formattedDateString, String bucket, String key, String secret){
        string auth;
        
        String stringToSign = method+'\n'+bucket+'/'+filename+'\n';
        Blob mac = Crypto.generateMac('HmacSHA1', blob.valueof(stringToSign), blob.valueof(secret));
        String sig = EncodingUtil.base64Encode(mac);
        auth = 'AWS' + ' ' + key + ':' + sig;
        
        
        return auth;
    }

I have followed the link here (https://developer.salesforce.com/forums/?id=906F0000000BMDFIA4) for the approach used.

I am able to upload the file to same bucket from ruby or javascript using the aws sdk's, but it is giving me a response code of 400 (Bad Request).
I think this is a problem of the process of signing request.

It will be highly appreciated if someone can help me here.
VaasuVaasu
You have generated AUTH header but not setting it to the request.
Aayush MallAayush Mall

Thank you Vaasu.

Sorry, I forgot to add that line, I am adding the AUTH in the header too. 

req.setHeader('Authorization' auth);
Nitin Rawat 9Nitin Rawat 9

Hi Aayush, 

I have the same requirment to upload file directly to s3 bucket through VF page without saving it in SF.
Could you help me on this.


Thanks in advance!! :)

Amol waghAmol wagh

Hi Aayush Mall,

Please refer this (https://www.cloudwaale.com/post/how-to-store-attachment-file-into-aws-s3-from-apex-code) here you will find all step by step guide to upload file into AWS from Apex class,
 

Thanks,
Amol, www.cloudwaale.com