-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added support for arrays in 'data' #40
Conversation
I saw the #38 pull request and agree that it's better to use |
An array is not a valid JSON object. It is better to send your data to the server in a valid JSON format. |
Not sure I understood your comment. /stask
|
@stask why not just use JSON and keep the protocol semantically consistent? JSON is very easy to build and parse and it saves you a lot of time building and parsing the strings. |
@elgs I'm not trying to change the protocol. What i'm suggesting is part of HTTP. FormData object allows it. Checkboxes work like that, combo boxes with multiple selection work like that. Field with multiple values gets encoded into something like this: |
Yes this is standard way to send data when you have checkboxes with multiple choices. We must support it. |
That is only the case for GET requests. Angular by default converts the config.data to JSON if it is an object.
rather than
This will save you a lot of url query space for big objects and would be better API on the server side if you are designing a service API with the JSON object as an input param. |
@danialfarid You're cancelling default Angular behaviour by changing transformRequest here: |
Yes you are right. I just realize that before reading this. I have put a fix in the code, gonna release a new version with a fix tomorrow. |
hmm I realized that what I do is a bit different from angular. Angular sends the whole json data as encoded request body, but here I go over each data key and add them to formData. The thing is that here I need a formData name for the actual data. A solution is to convert the whole data to json and send it as "data" form field. |
@danialfarid an array is a valid JSON object, based on the definition from this website: http://www.json.org, I'm not sure if this website is the official definition of JSON, however, I tested [1,2,3] in http://jsonlint.com, and it's said to be valid. |
Yes you are right, thanks for letting me know. |
I think the current situation already has given a great flexibility to transfer data in whatever format we want, thanks to JSON, or am I missing anything? @stask can you please share your use case about this requirement, or make it a little bit more specific by showing some code which you expect the data's format would be? |
@elgs Here is my use case: I have a form with few fields (name, description, tags) and a file field. Tags field is composed of several fields with the same name 'tags'.
As you can see, the file 'part' has Content-Type application/x-gzip. While other 'parts' don't have Content-Type.
And on the server side the field 'tags' is properly parsed into an array by middleware. @danialfarid When i said "encode non-binary parameters as different 'part' in FormData with encoding 'application/json'", i meant that we can try sending non-file parts as Blob, where Content-Type can be specified. I'm not sure if standard middlewares will be able to parse it properly though, will try it later today and will let you know. |
Nope, seems like using Blob doesn't solve the issue. It's parsed as regular file on server side. if (config.data) {
formData.append("data", new Blob([angular.toJson(config.data)], {type: "application/json"}));
} It produced following in tcpdump:
And on server side, i got two files, one for the actual file i sent, another one for the JSON Blob:
I'll try to dig a little more, but not sure there is any option besides the one i suggested originally. |
Can you try sending your data with $http.post() without the file and see if you can receive it on the server side any better. I assume $http.post() does the same thing and you need to convert string to json on your server side. |
by the way, I think for your situation it is better to send the file alone and upload it and once it is uploaded completely then send the other related data with a $http.post() along with the file id that the server returns. There have been some known issues with Amazon S3 when uploading file along with data. I personally like to use upload just for the file since it is inherently a slow process, and then once the whole slow upload is complete do the other things and send the small data in a separate request and associate them with the uploaded file using an id. This is not an answer to this issue but just a design suggestion. |
@danialfarid Yes, i tried using
|
I see, |
@danialfarid Well, to support nested structures you can use something similar to what was suggested in #38 (i would suggest refactoring it to support unlimited depth). It does require special handling on server side. Rails does it automatically, but other frameworks might not (in Clojure you have to add another middleware for instance). Regarding your last suggestion -- primitive values (strings, numbers) are encoded as plain strings, objects and arrays are encoded as JSON. Since it's not possible to specify content type for string parts of the multipart request, the only way to determine whether the value is just string or JSON string is by field name (either hard-coded logic or some kind of convention for field names). So it's not the most convenient option. |
@stask Could you verify if #38 works with Rail or Clojure or any framework you are working with. So if you have the nested array like this
and they are sent as separate form data element like this:
What would server create for the data. Also for this example:
I can add an option to the config to convert the arrays to the equivalent indexed keys in the form data to make it easier for these frameworks but not all frameworks would support that so by default it would convert them to JSON. |
@danialfarid i'm not sure i'm explaining myself good enough. I'll try again. My pull request adds support for standard HTTP feature -- fields with multiple values. Forms with multiple selection (<select multiple...) and checkboxes use that. So, bottom line -- i see two options (besides just saying that fields with multiple values aren't supported):
|
I added an option to upload
Which could take care of appending arrays to the formData as you expect. Since it is server specific implementation by default it would convert the data to JSON format but you can specify a |
Had the same problem. Your formDataAppender fix works for me (using NodeJS & Express on the server side) |
ok cool, I added some notes about this to the REAME file. |
Support for sending multiple values for a field (for example, tags).