How can I PUT a new file to a node using services 3 without overwriting the existing file?
Background

Services uses drupal_execute() with the node form to save updates to nodes, which won't entirely merge updates in with existing data.

If the update doesn't set a field at all, then it won't overwrite what's there, so in a sense it does merge data in that case. For instance, in your example, you don't set "title" in your update, and therefore it won't overwrite that field.

However, if you set a field, it will overwrite whatever was there previously. So, in your example, since you are setting "field_dl_file", it will overwrite whatever was previously there with whatever you set now. As you saw, this causes any existing files to be overwritten.

Solution

Probably the best solution (and I assume the one intended by the Services team) is to load the previous value of the "field_dl_file" in your script (via a retrieve call to the REST interface), then call the update with both the new value as well as the old value. In other words, merge the old data in with the new data on the client side (inside the script that interacts with the REST interface).

Another possible solution is to manually merge your "field_dl_file" field with existing values inside node_resource.inc (line 365 or so). I assume the Services team never intended this, and it would require changing the module directly (since there aren't any hooks there), so I can't really recommend it. It would, however, ease the work needed in the client-side script, which could be a benefit depending on your implementation.

Note: I referenced Drupal 6 code, though I'm fairly sure it applies to Drupal 7 as well (that part of Services 3 didn't change as far as I know).