[SalesForce] Uploading an attachment with Request

I've been struggling with Salesforce's attachment upload API for a while, and having a hard time getting Request to format its request in a way that Salesforce is happy with. Here's what I'm working with so far:

  const request = require('request');
  const fs = require('fs');

  const options = {
    method: 'POST',
    uri: 'https://instance.salesforce.com/services/data/v38.0/sobjects/Attachment',
    headers: {
      'Authorization': 'Bearer token',
      'Content-Type': 'multipart/form-data',
    },
    multipart: [
      {
        'content-disposition': 'form-data',
        name: "entity_content",
        'content-type': 'application/json',
        body: JSON.stringify({
              "Name": "test",
              "Type": "text",
              "Description": "test",
              "Keywords": "test",
              "ParentId": "id",
        })
      },
      {
        'content-disposition': 'form-data',
        name: 'Body',
        filename: 'test.txt',
        'content-type': 'text/plain',
        body: fs.createReadStream('test.txt')
      }
    ]
  };

  const req = request(options, (err, httpResponse, body) => {
    if (err) {
      return console.error('upload failed:', err);
    }
    console.log('Server responded with:', body);
  })

At the moment, I'm getting "You have sent us an Illegal URL or an improperly formatted request." When I made a couple attempts using Request's multipart/form-data syntax rather than the multipart related, I had the slightly more helpful message "Multipart message must include a non-binary part," but my actual request looked farther from the example Salesforce gives in their docs.

Best Answer

As it turns out, just using the regular formData object with multiple keys was the way to go.

  const options = {
    url: 'https://instance.salesforce.com/services/data/v38.0/sobjects/Attachment',
    headers: {
      'Authorization': 'Bearer key',
      'Content-Type': 'multipart/form-data',
    },
    formData: {
      entity_document: {
        value: JSON.stringify({
            "Name": "test",
            "Description": "test",
            "ParentId": "id"
          }),
          options: {
            contentType: "application/json"
          }
        },
      Body: fs.createReadStream('./test.txt')
    }
  };

  request.post(options, (err, httpResponse, body) => {
    if (err) {
      return console.error('upload failed:', err);
    }
    console.log('Server responded with:', body);
  });
Related Topic