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, 2016 at 15:24
  • First Kb of formdata and first Kb of postContent? How I can grap 1Kb?
    – Dmitry
    Oct 8, 2016 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, 2016 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, 2016 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, 2016 at 14:41

1 Answer 1


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());

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .