How to programmatically submit a form that has a file-field using drupal_form_submit()?
This wasn't as hard as I expected; Drupal has different handling for fields with '#type' =&gt; 'file' as opposed to other types. There are two ways of solving the problem. One is simply adjusting the request-payload, expressed here as a curl command:



curl -i \ 
    'https://example.com/drupal/my_rest/my_resource' \
    -H 'Accept: application/json' \
    -H 'Content-Type: multipart/form-data' \
    -F "files[spreadsheet]=@my_spreadsheet.xlsx" # note the weird field-name
# This automatically uses the POST method, so Drupal reads it as a 'create'


Drupal munges file-field-names by default apparently apparently to match the file.inc code. This is stated expressly in comments:

if (!isset($element['#name'])) {
    $name = array_shift($element['#parents']);
    $element['#name'] = $name;
    if ($element['#type'] == 'file') {
        // To make it easier to handle $_FILES in file.inc, we place all
        // file fields in the 'files' array. Also, we do not support
        // nested file names.
        $element['#name'] = 'files[' . $element['#name'] . ']';
    }


If you want to API-endpoint users from the implementation shown above, the other solution is to explicitly provide a '#name' value for the file-field in question, as should be obvious:

return array(
        'spreadsheet' =&gt; array(
            '#type' =&gt; 'file',
            '#name' =&gt; 'spreadsheet_file', // &lt;-- adding this prevents name-munging
            '#title' =&gt; 'Spreadsheet file',
            // ...


Note of course that the above might have consequences for other sections of code if the file used to be expected under the old name.