I want to upload files from visualforce to salesforce org as attachment. When I send request with pdf, doc, rar etc. code worked correct and I can download attachment.

But when I try to save image as attachment it saves but can't open it as image.

It just little square that shows here must be image. I tried to change contentType but it doesn't help.

Here is my code:

Visualforce page:

<input type="file" id="inpFile" value="Choose file" multiple="true"/>


function sendFileToServer(formData,status, filename, fileres){
  var sfdcHostName = window.location.host.split('.')[1];
  var materialName = $("#materialName").val();
  var materialTheme = $("[id$='materialTheme'] option:selected").text();

  $("#AddMaterialButton").on('click', function() {

  var uploadURL = 'https://' + sfdcHostName + '.salesforce.com/services/apexrest/DragAndDrop/v1?FileName=' + filename + '&FileResolution=' + fileres + '&MaterialName=' + materialName + '&MaterialTheme=' + materialTheme;
  var jqXHR=$.ajax({
    xhr: function() {
      var xhrobj = $.ajaxSettings.xhr();
      if (xhrobj.upload) {
        xhrobj.upload.addEventListener('progress', function(event) {
          var percent = 0;
          var position = event.loaded || event.position;
          var total = event.total;
          if (event.lengthComputable) {
            percent = Math.ceil(position / total * 100);
            //Set progress
        }, false);
      return xhrobj;
    url: '/services/proxy',
    beforeSend: function(xhr) {
      xhr.setRequestHeader('SalesforceProxy-Endpoint', uploadURL);
      var sfdcSessionId = $('#sessionId').html();
      xhr.setRequestHeader('Authorization', ' Bearer ' + sfdcSessionId);
      xhr.setRequestHeader('X-User-Agent', 'MyClient');
    type: "POST",
    contentType: null,
    crossDomain: true,

    processData: false,
    cache: false,
    data: formData,
    success: function(data, textStatus){

Web Service Method:

    global static String attachDoc(){
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        res.addHeader('Access-Control-Allow-Origin', 'https://c.eu11.visual.force.com/apex/MainPage');
        res.addHeader('Content-Disposition', 'attachment');

        String fName = req.params.get('FileName');
        fName += '.';
        String fRes = req.params.get('FileResolution'); 
        String materialName = req.params.get('MaterialName');
        String materialTheme = req.params.get('MaterialTheme');

        Blob postContent = req.requestBody; 

        List<Material__c> materials = [SELECT Id, Name, Theme__c FROM Material__c WHERE Name = :materialName AND Theme__c = :materialTheme];
        Id parentId;
        if(materials.isEmpty()) {
            Material__c material = new Material__c();
            material.Name = materialName;
            material.Theme__c = materialTheme;
            insert material;
            parentId = material.Id;
        } else {
            parentId = materials[0].Id;

        Attachment a = new Attachment (ParentId = parentId,
                                   Body = postContent,
                                   Name = fName+fRes);
        insert a;
        return a.Id;
  • Assuming other data types are coming through, images should be no different. Could you grab the first 1kb or so from the image you're uploading (e.g. via a hex editor), and the first 1kb or so from the image you download after uploading, and post them there? Maybe there's something wrong with character encoding or something. I don't see anything inherently wrong with the code you've written.
    – sfdcfox
    Oct 8 '16 at 15:24
  • First Kb of formdata and first Kb of postContent? How I can grap 1Kb?
    – Dmitry
    Oct 8 '16 at 19:13
  • In JS, btoa can give you a base 64 dump, and you can read the first few characters with substring. For Apex, use EncodingUtil base64Encode to get a printable string, then string.left to get the beginning characters. Make sure they match.
    – sfdcfox
    Oct 8 '16 at 19:20
  • I don't know how I can to grap data from formData, but when I write this command in JS btoa(files[0].slice(0,10)) I get this: "W29iamVjdCBCbG9iXQ==". In web service I wrote String strt = EncodingUtil.base64Encode(postContent); System.debug(loggingLevel.Error, '*** strt: ' + strt); and get *** strt: LS0tLS0tV2ViS2l0Rm9ybUJvdW5kYXJ5RTNuOE05MEU0RTdwS1 .... They are different. When I try to upload .docx JS command show the same result as previous. What it can be?
    – Dmitry
    Oct 9 '16 at 13:33
  • 1
    LS0t... decodes to ------WebKitFormBoundaryE3n8M90E4E7pK which means it's a multipart/form upload. You'll have to figure out a way to either change the request so the file is directly in the requestBody, or find a way to parse a multipart/form upload. I haven't had much luck with the latter, but you should be able to fix your JavaScript to not use multipart/form upload mode. You'll want to check the documentation, as I'm not sure how to arrange this in jQuery.
    – sfdcfox
    Oct 9 '16 at 14:41

Solution of problem with changing formData as inner parameter in sendFileToServer function directly on filesToUpload[j]. Thanks to sfdcfox for response and help.

function handleFileUpload(files,obj){
  filesToUpload = files;
  statuses = [];
  for (var i = 0; i < filesToUpload.length; i++) {
    var status = new createStatusbar(obj); //Using this we can set progress.
    statuses[i] = status;
    $("#saveMaterialButton").on("click", function () {
      for (var j = 0; j < filesToUpload.length; j++) {
        sendFileToServer(filesToUpload[j],statuses[j],encodeURI(filesToUpload[j].name.split('.')[0]), filesToUpload[j].name.split('.').pop());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.