I have an API consisting of ASP.NET webservices callable through GET/POST/SOAP.
A new functionality will require me to accept files through this webservice. Basically I’m allowing users to upload files to a file archive through the API, which they’d otherwise do by logging into our browser based administration system.
The API needs to be as easily consumed as possible. I’m thinking of dropping SOAP support since our PHP clients mainly use the GET/POST methods, and the .NET clients don’t mind either way. With that as a prerequisite, I’m thinking of simply creating an UploadFile(fileName) method, and the requiring the user to send the file through POST as a normal file upload.
However, I will not be able to specify the file field as a parameter to the method, right? So if I simply state in the documentation ‘file should be sent in POST field called ‘File”, would that pose any problems when I need to read the file?
All files are in binary format, PDF’s, various image formats, FLV and so forth. Also, file sizes will mainly be in the 2-20MB vicinity, but given the above solution, would I have any troubles accepting files in the 250MB area?
Receiving a file this way would result in the file being loaded completely into memory, before I write it to disk – is there any way around this, besides letting the service receive a Stream and thus disabling me from accepting other parameters, and hindering the easy usage of the service?
Besides what’s possible on my side, I’m also curious in regards to how I make it as easy as possible for the callees to send the file. I’m guessing POST is one of the most accessible ways of receiving the file, but if anyone has any comments, I’d like to hear them as well.
There’s no reason you can’t include additional POST (or GET, for that matter) parameters. I would probably take the filename as an additional POST parameter myself, so that clients that automatically use the local filename in the request can rename easily. If I expected naming conflicts, I may even return a server chosen name in the event of conflicts…I think the REST folks use some sort of HTTP Created status code for that.
You’ll need to tweak the maxRequestLengths and executionTimeouts in web.config. And, if anyone tries a 250MB upload over dialup – well, let’s just say it probably won’t work.
ASP.NET 2.0+ spools uploaded files to disk as they come in, to avoid preloading the entire request into RAM. Tweak web.config’s requestLengthDiskThreshold as appropriate to balance speed and memory usage. You couldn’t take a Stream if you wanted to…though you may be able to take in a byte[] array. I’m really not sure what that’d mean though….
For small files, you could do base 64 which should be trivial for clients. But, for 20MB – the overhead wouldn’t be worth it.
There’s a bunch of different ASP.NET file upload components – which basically hook up to Begin_Request as an HttpModule, and intercept the request stream for any multippart/form-uploads. With ASP.NET 2.0, this is probably unnecessary, unless you want to provide some sort of progress callback or something. If that’s the case – the mechanics of them should work with a web service the same.
RFC 1867 is the relevant spec, but this upload component does a good job of laying out what the request looks like if you’re intent on parsing your own.
The one question mark I would have, is what the level of support for multipart/form-data in the http libraries of your clients is. I’d suspect that it’s pretty good all around, but you may want to check.