3 ms·
I'd love to see some guidance on how you're supposed to do file uploads (think: uploading an image avatar for a user) and fit it into the REST structure. These
by blakeyrat 10y ago
I'd love to see some guidance on how you're supposed to do file uploads (think: uploading an image avatar for a user) and fit it into the REST structure. These guidelines don't even mention "x-www-form-urlencoded" except in a bit of fluff about CORS.
Made more frustrating by Microsoft's own WebAPI2 basically having zero support for file uploads, meaning we had to go way outside the library to code support for it.
Not sure why that's such a blind spot. Doesn't every web service need to upload files eventually?
- gedy 10y agoPOST /users/{id}/avatar ? What additional guidance would you expect?
- blakeyrat 10y agoWell, for one thing, it's a huge PITA to have 99 controllers that all take JSON and one oddball that has to take forms-urlencoded because you can attach a file. This is out of the scope of this document, but I'd also like to see some guidance on how to implement the controller for that oddball using Microsoft's own WebAPI2 library. I ended up having to go entirely outside the library and implement it as a generic .ashx handler, but is that literally the best way? It feels like a horrible nasty hack.
- niftich 10y agoYou're thinking of 'multipart/form-data' with a content-disposition of 'attachment', which is the usual way of uploading binary blobs to a controller resource. But conceivably you could have controllers that accept a PUT or a POST of an 'image/jpeg'. Why wouldn't you, if you're aiming for image uploads?
- blakeyrat 10y agoYou're right, I had the wrong MIME type. It's been ages since I was working with this stuff. To answer your second question: because I simplified the example. We run a health insurance website and we need to support life changes events either with or without supporting documentation. It makes no sense to have two separate controllers, as that would mean you could have a successful file attached to an errored-out life change, or the reverse. But look, never mind. I was just asking because our solution to this problem I imagine most REST APIs would eventually come across felt really hacky and awful and I'm really not proud of the code I wrote to support it, but maybe we're the weirdo freaks and nobody else has to do anything more complicated than assign a file to a user ID.
- icebraining 10y agoI agree with you, though I'd say that's mostly a problem of JSON, which doesn't cleanly support binary data, not REST itself. Still, base64 ain't so bad, it's only a 33% increase over raw bytes.
- JimDabell 10y agoThere's a lot wrong with that. POST has the semantics of sending data to a resource. What you're essentially saying here is that you're sending an image to the avatar resource. That's not what you're trying to do though. What you're actually trying to do is place a resource at that URI. For that, you use PUT, not POST. Then we have the problem of conflicts. What if there's a resource there already? Now you need to introduce If-None-Match and things like that. Then we have the problem that /users/{id}/avatar might be an inappropriate place to put that resource. Maybe the server needs to store it on a CDN or something. Finally, we have the problem that this isn't a REST API you are describing, since the client and server implementations are coupled together. In a REST API, the API documentation doesn't instruct developers where to place resources, the server instructs clients where to place resources. One way of handling avatar upload in a REST API would be for the User media type to define an action that sets the avatar image. The client would then follow that action to upload the image. From an HTTP perspective, a likely implementation would be to POST to a URL that returns a 201 with the location of the newly-uploaded avatar. But the key thing is that the server defines how the client does that, you don't hard-code behaviour into all your clients. If that's too abstract for you, think of it as <form action="/upload-avatar" method="POST">. It's simple to implement – much easier than hard-coding a load of URI patterns in all your clients and hoping you'll never have to change them. From a guidance standpoint – for an API, define the structure of common interactions (e.g. file upload), and have your media types include those structures when they need clients to be able to change state. Your API documentation should describe your media types and relationships, and never URI structures. If you predefine URI structures, it's not a REST API.
- ranyefet 10y agoYou can turn the uploaded image into base64 string in the client and then just post it as part of your JSON payload.
- adamors 10y agoThis is what I've been doing and it's very simple for both client apps and on the server. I don't know if this is feasible for larger files tho.
- abraae 10y agoAnd send emails.
- ChrisAtWork 10y agoIt turns out that uploading files is hard. Files come in a variety of sizes, networks sometimes don't work, browser processes come-and-go, some users expect restart semantics, some don't...