1

We are attempting to use a Named Credential in a Callout from Apex to send an uploaded image to AmazonS3 through our VF Page.

In testing, our GET request succeeded, but POST/PUT requests fail with the error/code below.

This is the line that's throwing an error:

HttpResponse res = http.send(req);

We've check out this question and followed the suggested solutions, but they did not seem to work in this case.

We are running into these errors (photo and text below):

enter image description here

VM55:1 POST https://simplyhome--sb3--c.visualforce.com/services/Soap/package/May11UploadTest 500 (Server Error)
(anonymous) @ VM55:1
send @ connection.js:594
sforce.SoapTransport.send @ connection.js:1012
sforce.Connection._invoke @ connection.js:1709
sforce.Apex.execute @ apex.js:60
s3upload @ S3UploadTest:73
onclick @ S3UploadTest:142

S3UploadTest:142 [Violation] 'click' handler took 297ms

S3UploadTest:92 Uncaught (in promise) sforce.Xml {faultcode: "soapenv:Client", faultstring: "System.UnexpectedException: Script-thrown exceptio…↵Class.May11UploadTest.request: line 23, column 1"}
s3upload @ S3UploadTest:92
onclick @ S3UploadTest:142

VM55:1 XHR failed loading: POST "https://simplyhome--sb3--c.visualforce.com/services/Soap/package/May11UploadTest".

Here's our current Apex Code:

global class May11UploadTest {
        
    webservice static string request(blob file) {
        String fileName = EncodingUtil.urlEncode('test.jpg', 'UTF-8');
        String attachmentBody = EncodingUtil.base64Encode(file); 
        String formattedDateString = Datetime.now().formatGMT('EEE, dd MMM yyyy HH:mm:ss z');
        String region = 'us-east-1';
        String service = 's3';  
        String host = service+'.'+region+'.amazonaws.com';
        
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:aws3' + fileName);
        req.setMethod('POST');
        req.setHeader('Content-Encoding', 'base64');
        req.setHeader('Accept', 'image/jpeg');
        req.setHeader('Content-Type', 'image/jpeg');
        req.setHeader('Content-Length', string.valueOf(attachmentBody.length()));
        req.setHeader('host',host);
        req.setHeader('Date', formattedDateString);
        req.setBody(attachmentBody);
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        System.debug(res.getBody());
        System.debug(res.getStatusCode());
        System.debug(res.getStatus());
        
        if(res.getStatusCode() == 200) {
        return res.getBody();
    }
    
        return res.getStatus();
    }
}

Here is our VF page Code:

<apex:page standardStyleSheets="false" showHeader="false" sidebar="false">
<apex:stylesheet value="{!$Resource.styleForImageUpload}"/>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
</head>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.839.0.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
<apex:includeScript value="/soap/ajax/30.0/connection.js"/>
<apex:includeScript value="/soap/ajax/30.0/apex.js"/>
sforce.connection.sessionId = "{!$Api.Session_ID}";
function addRow(tableID) {
  var table = document.getElementById(tableID);
  var rowCount = table.rows.length;
  var row = table.insertRow(rowCount);
  var colCount = table.rows[0].cells.length;
  for(var i=0; i<colCount; i++) {
    var newRow = row.insertCell(i);
    newRow.innerHTML = table.rows[0].cells[i].innerHTML;
    newRow.childNodes[0].value = "";
  }
}
function deleteRow(row) {
  var table = document.getElementById("data");
  var rowCount = table.rows.length;
  if (rowCount > 1) {
    var rowIndex = row.parentNode.parentNode.rowIndex;
    document.getElementById("data").deleteRow(rowIndex);
  }
  else {
    alert("Please specify at least one value.");
  }
}


async function s3upload() {
  var uniqueId,
  element = document.getElementById("uniqueId").value;
  if (element != "") {
      uniqueId = element;
  }
  else {
       alert("Please specify a Unique ID. This has been emailed to you.");
       return;
  }
  var updatedFileName = document.getElementsByClassName("updatedFileName");  
  var files = document.getElementsByClassName("uploadFile");
  function toArray(arr) {
    return [].slice.call(arr);
  }
  var files_arr = toArray(files).filter(v => v.files[0] != null);
  var actual_files = new Array();
  var errors_arr = new Array();
  files_arr.forEach(function callback(file_obj,i){
    actual_files[i] = file_obj.files[0]
  })   
  var updated_file_names_arr = toArray(updatedFileName);
  var image_count = actual_files.length;
  var final_image_index = image_count-1;
  var success_count = 0;
  var error_count = 0;
  var final_message = "";
  
  for ( var i = 0; i <= final_image_index; i++ ) {
    var file = actual_files[i];
    var fileName = updatedFileName[i].value;
    var resp = sforce.apex.execute("May11UploadTest","request",{file: file});
    debugger; 
  };
  
   

    var total_count = success_count + error_count;
    var uploaded_percent = 100 * total_count / image_count;
    document.getElementById("progress").value = uploaded_percent;
    if (uploaded_percent == 100) {
      var final_message = success_count + " images uploaded successfully. ";
      if (error_count != 0) {
          final_message += "Errors encountered uploading: ";
          final_message += errors_arr;
      };
      setTimeout(function() {
        alert(final_message);
      },5);
    };
  };
  
</script>
<br></br><br></br><br></br>
<div id="main">
 <apex:form >
    <apex:actionFunction action="{!May11UploadTest}" name="s3test"/>
 </apex:form>
  <h1>Please Upload Home Images</h1>
  <table id="header" class="data-table data-table-horizontal data-table-highlight">
    <tbody>
      <tr>
        <td> Please Enter Unique ID (Emailed to you)</td>
        <td> <input type="text" id="uniqueId" value="" placeholder="Enter Unique ID" required="true"/></td>
        <td></td>
     </tr>
    </tbody>
  </table>
  <table id="data" class="data-table data-table-horizontal data-table-highlight">
    <tbody>
      <tr>
        <td><input type="file" class="uploadFile" value="false"/></td>
        <td><input type="text" placeholder="Image of what?" class="updatedFileName"/></td>
 <td><a type="button" value="Delete" onclick="deleteRow(this)"><i class="fa fa-trash-o fa-fw"></i></a></td>      
 </tr>
      <tr>
        <td><input type="file" class="uploadFile" value="false"/></td>
        <td><input type="text" placeholder="Image of what?" class="updatedFileName"/></td>
 <td><a type="button" value="Delete" onclick="deleteRow(this)"><i class="fa fa-trash-o fa-fw"></i></a></td>      </tr>
      <tr>
        <td><input type="file" class="uploadFile" value="false"/></td>
        <td><input type="text" placeholder="Image of what?" class="updatedFileName"/></td>
 <td><a type="button" value="Delete" onclick="deleteRow(this)"><i class="fa fa-trash-o fa-fw"></i></a></td>      </tr>
      <tr>
        <td><input type="file" class="uploadFile" value="false"/></td>
        <td><input type="text" placeholder="Image of what?" class="updatedFileName"/></td>
 <td><a type="button" value="Delete" onclick="deleteRow(this)"><i class="fa fa-trash-o fa-fw"></i></a></td>      </tr>
      </tbody>
  </table>
  <table>    
  <tr>
  <div class="pull-right">
    <input type="button" value="Add" class="top-buffer" onclick="addRow('data')" />
  </div>
  </tr>
  <tr>
      <div class="pull-center">
<input type="button" class="top-buffer" value="Submit All Images" onclick="s3upload()" />
    </div>
  </tr>
  <tr>
    <progress id="progress" max='100' value='0'></progress>
   
  </tr>
  </table>
  </div>
  </apex:page>

Thanks in advance for your assistance!

2
  • This may be a little late, but have you tried including a slash "/" between your named credential callout and rest of the endpoint? For example req.setEndpoint('callout:aws3/' + fileName); Jul 8, 2021 at 16:52
  • @gale-force-wizard - Yes, unfortunately, we were unsuccessful with that option as well. Jul 13, 2021 at 13:34

0

You must log in to answer this question.

Browse other questions tagged .