Posting a File and Associated Data to a RESTful WebService preferably as JSON

This is probably going to be a stupid question but I'm having one of those nights. In an application I am developing RESTful API and we want the client to send data as JSON. Part of this application requires the client to upload a file (usually an image) as well as information about the image.

I'm having a hard time tracking down how this happens in a single request. Is it possible to Base64 the file data into a JSON string? Am I going to need to perform 2 posts to the server? Should I not be using JSON for this?

As a side note, we're using Grails on the backend and these services are accessed by native mobile clients (iPhone, Android, etc), if any of that makes a difference.


I asked a similar question here:

How do I upload a file with metadata using a REST web service?

You basically have three choices:

  • Base64 encode the file, at the expense of increasing the data size by around 33%.
  • Send the file first in a multipart/form-data POST, and return an ID to the client. The client then sends the metadata with the ID, and the server re-associates the file and the metadata.
  • Send the metadata first, and return an ID to the client. The client then sends the file with the ID, and the server re-associates the file and the metadata.

  • You can send the file and data over in one request using the multipart/form-data content type:

    In many applications, it is possible for a user to be presented with a form. The user will fill out the form, including information that is typed, generated by user input, or included from files that the user has selected. When the form is filled out, the data from the form is sent from the user to the receiving application.

    The definition of MultiPart/Form-Data is derived from one of those applications...

    From http://www.faqs.org/rfcs/rfc2388.html:

    "multipart/form-data" contains a series of parts. Each part is expected to contain a content-disposition header [RFC 2183] where the disposition type is "form-data", and where the disposition contains an (additional) parameter of "name", where the value of that parameter is the original field name in the form. For example, a part might contain a header:

    Content-Disposition: form-data; name="user"

    with the value corresponding to the entry of the "user" field.

    You can include file information or field information within each section between boundaries. I've successfully implemented a RESTful service that required the user to submit both data and a form, and multipart/form-data worked perfectly. The service was built using Java/Spring, and the client was using C#, so unfortunately I don't have any Grails examples to give you concerning how to set up the service. You don't need to use JSON in this case since each "form-data" section provides you a place to specify the name of the parameter and its value.

    The good thing about using multipart/form-data is that you're using HTTP-defined headers, so you're sticking with the REST philosophy of using existing HTTP tools to create your service.


    I know that this thread is quite old, however, I am missing here one option. If you have metadata (in any format) that you want to send along with the data to upload, you can make a single multipart/related request.

    The Multipart/Related media type is intended for compound objects consisting of several inter-related body parts.

    You can check RFC 2387 specification for more in-depth details.

    Basically each part of such a request can have content with different type and all parts are somehow related (eg an image and it metadata). The parts are identified by a boundary string, and the final boundary string is followed by two hyphens.

    Example:

    POST /upload HTTP/1.1
    Host: www.hostname.com
    Content-Type: multipart/related; boundary=xyz
    Content-Length: [actual-content-length]
    
    --xyz
    Content-Type: application/json; charset=UTF-8
    
    {
        "name": "Sample image",
        "desc": "...",
        ...
    }
    
    --xyz
    Content-Type: image/jpeg
    
    [image data]
    [image data]
    [image data]
    ...
    --foo_bar_baz--
    
    链接地址: http://www.djcxy.com/p/1330.html

    上一篇: 如何将JSON数据写入文件?

    下一篇: 将文件和关联数据发布到RESTful WebService(最好是JSON)