5

Using Services 3 I have it working fine to add a file using

endpoint/file
{"uid":"1","filesize":"99999","filename":"whatever.bin","file":"BASE64_ENCODED_DATA"}

and also to add a node with that file using

endpoint/node
{"title":"testrest1","type":"dl","field_dl_file":{"und":[{"fid":582}]},"uid":"1","language":"und"}

But how can I add a new file to the node? When doing PUT

endpoint/node/999 
{"field_dl_file":{"und":[{"fid":999}]},"uid":1,"language":"und"}

It just overwrites the existing file. Trying to POST gives a whole bunch of errors.

4

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).

  • Thanks, its definitely a solution worth trying but as it creates more http requests from the app and I expect these file lists to get quite large I would prefer an update and create solution. I will look into it further and see if perhaps I can store the file list in android sharedpreferences (which will save unnecessary http requests). I would have thought this was quite a regular request and find it strange that there is not already a functionality for doing so. – 7wonders Feb 29 '12 at 18:39
  • I agree that it's strange, since it seems inefficient to force the client to do more HTTP requests. The second possible solution would probably work for you though: manually merge the new "field_dl_file" with the existing $old_node->field_dl_file before the drupal_execute() saves the node again (line 365 or so of node_resource.inc). It would require changing a contrib module though, which has obvious downsides. – Allan Wintersieck Feb 29 '12 at 19:03

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.