Get form parameters from multipart request without getting the files - java

I'm looking for a way to get the form parameters of a HTTP multi-part request in a Servlet-filter without uploading files (yet).
request.getParameterMap() returns empty. I understand this is because of the request being multi-part.
I've looked at commons.HttpFileUpload but this seems to be overkill for my situation. In this filter I'm only interested in the normal parameters, and don't want to handle the file-upload yet.
Edit: the main problem is that I need to have an intact HttpRequestObject further down the filter stack. The HttpFileUpload seems to consume part of the request data (probably by using the data stream object and closing it again.)

It's certainly not overkill, it's the right way and always better than writing the parser yourself. The Apache Commons FileUpload is developed and maintained for years and has proven its robustness in handling multipart/form-data requests. You don't want to reinvent the wheel. If you really want to do it (I don't recommend it), then read on the multipart/form-data specification and start with reading the HttpServletRequest#getInputStream() (warning: this is a mix of binary and character data!).
You can if necessary also write a Filter which makes use of Apache Commons FileUpload under the hood and checks every request if it is multipart/form-data and if so, then put the parameters back in the request parameter map with help of Commons FileUpload and put the uploaded files (or exceptions) as request attributes, so that it's finally a bit more transparently in your servlet code. You can find here a basic example to get the idea.
Hope this helps.

Just to add to the answers already provided - I had a very similar problem in that I was trying to add some CSRF validation to our existing web app. We decided to include a special token in each form using some JS and add a servlet filter to check that the token existed (therefore a generic, isolated solution).
The servlet would check if the token was present but broke for every form that provided a file upload option. Hence I landed at this page frequently while doing some googling.
The work around we used (while attempting to avoid any dealings with the uploaded files) was to get some JavaScript to add the token as a GET parameter, i.e. We modified the form's action URL to include the token and therefore could use the HttpServletRequest.getParameter() method for the token (and only the token).
I have tested this in IE, FF and Chrome and all seem to be happy.
Hope this helps anyone who also finds themselves in a similar situation.

The Oreilly Servlets website has some sample code which you can download customise and use. This includes MultipartRequest which sounds like it does what you require, it un-boxes a multipart request and allows access to the parameters and the files separately.

Commons FileUpload provides a mechanism to read request params from a multipart form upload.
There's a really great example of how to grab the request parameters here:
How to upload files to server using JSP/Servlet?

Related

Docusign: creating envelope with multiple documents in multipart request from Java

The Docusign Java SDK doesn't have built-in support for creating envelopes with multiple documents as binary. This is cumbersome for users. People asking about have been directed to this one-off example code using Java's native HttpsUrlConnection: Docusign Multipart Request To Create Envelope using java SDK (the current link for this source is here: https://raw.githubusercontent.com/docusign/code-examples-java/ee8489ca749a007767f07e1871ec9be100b5abb2/src/main/java/com/docusign/controller/eSignature/services/SendBinaryDocsService.java) or raw HTTP request as at Docusign - send envelope REST API (POST multipart/form-data ). The sample code uses the raw HttpsURLConnection class to make HTTP requests, different from how ApiClient uses Jersey to make requests.
Why is this common use case not just built into the SDK? The SDK does actually have some multipart support in ApiClient.java https://github.com/docusign/docusign-esign-java-client/blob/master/src/main/java/com/docusign/esign/client/ApiClient.java serialize() and invokeAPI() methods, using Jersey parts. Note that FormDataContentDisposition is used, which will result in individual parts having the name "form-data". Also this route is not available for the EnvelopesApi.createEnvelope() method.
It's tempting to just make a direct ApiClient.invokeAPI() call to try and make use of this, but the code starting "// Generate and add Content-Disposition header as per RFC 6266" seems like it overwrites the "entity" with each individual part, so this may not work with more than one part?
The documentation of the API is found here: https://developers.docusign.com/docs/esign-rest-api/how-to/send-binary/ Both the description and sample code use "Content-Disposition: file..." while the web spec states that for each individual part of a multipart body "The first directive is always form-data" (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) - which ApiClient itself does for its own multipart support.
ETA: experimentation shows that using "Content-Disposition: form-data" actually works fine
Clients are also asked to include "documentid=N" in the Content-Disposition, but it appears difficult to add this extra parameter at least when using Jersey's FormDataContentDisposition. If you look inside the source of glassfish FormDataContentDisposition / ContentDisposition you can see that only a fixed list of parameters will be included in the string buffer.
It would greatly help SDK users if we could get:
official support for creating envelopes with multiple binary documents in the official SDKs
alternatives to proprietary customizations of Content-Disposition header
this would make life much easier for Java SDK consumers. Apologies if I got anything wrong here.
A well written question. To better register your sdk enhancement request, see feedback.docusign.com and request via your DocuSign sales person.
THE SDKs are autogenerated from our swagger file. So your request would be a large project and is not currently planned.
While uploading with base64 encoding is inefficient, it works fine.

How to execute DELETE and PUT methods in Java Servlets

I'm looking for any way to run PUT and DELETE methods for Java Servlets. In general, I have a simple application with web control (WAR) connected with EJB project that controls a simple list of libraries.
For each of CRUD actions I would like to use different different method:
Creating by POST,
Reading by GET,
Update by PUT,
Delete by DELETE
However create I make by simple form with post method, read (list) is executed by simple entering GET in the URL address (without form), but I have no idea how could I use put and delete for their purposes.
Unfortunately online resources I found didn't answer that question, but I'm just curious how I could use id.
I assume removing by e.g. /Servlet/:libraryId (without any body), update by the same URL schema (with updated schema). doPut() and doDelete() should just run proper actions in the EJB.
There's no way on the HTML level to create a DELETE request in a form submit (it's always GET or POST, except you start to write your own browser that handles the kind of non standard HTML you proposed), all you can do is to submit a value (taken from a hidden field, radio button, whatever) that expresses which action should be taken in the doPost() or doGet() handler on the server.
But then there's nothing special about DELETE on the http protocol level. The whole request is just a sequence of bytes, where the first few define the method (PUT, GET, DELETE, PATCH...), followed by space etc.
As far as your server is concerned you could even use web sockets to accept connections and create responses to self defined fantasy methods. If you're using servlets, you have doPut(), doGet() and doDelete() available anyway. To handle other http methods you'd have to override the service() method.
On the client side Angular's HttpClient allows for all three methods that you need, you could use jquery's ajax, or there's again the web socket approach on the client too, as long as the browser plays along.
If it is a Java client, again there are web sockets (but you'd want to send some valid http request instead of "Hello", as done in the example¹.), HttpUrlConnection and the Apache HttpClient, at a first glance.
As for testing, there are browser extensions available that let you compose requests other than PUT and GET, SoapUi as a tool is very popular, IntelliJ even has a http client, that allows you to type the complete request as plain text.
¹ If you have a hand crafted server that agrees to such a "Hello" protocol, that's fine too. Its just not http.
Since there was quite some confusion in the question, as it turned out, I'd like to promote the idea some more to write your own Http client/server with webSockts. You have ready made examples for the socket stuff, so that's easy.
But it's more interesting then, that you're at the raw tcp/ip level that http is built on, all this framework-redirection (servlets, whatever) drops away and you're left with a single text basically (well, a byte stream), that's the http request. All the magic is gone, things are obvious and simple, just as specified.

HTTP(S) request to another server using Java tools?

I'm new to this and I need my Java program to send http or https requests on the different websites(for example, Amazon)
so it can get the HTML code and than I would be able to find information(price on some goods) that I need via Pattern class.
Did anybody faced with that task? Maybe you used JSON or other tools? Thank you.
It seems that Amazon have an API. You should using instead of trying to parse their website.
Regarding libs to call webservices in JAVA, you could use Retrofit.
There are several parts to what you are asking:
Constructing / determining what to include in the HTTP request
Issuing the actual HTTP request
Parsing the response
The first and last are dependent on the particular service / API you are invoking, though if the API response is in a standard format (e.g. JSON), there are libraries that can help you interpret the response (though exactly which fields in the response mean something to you, will depend on the particular API and your application). Issuing the HTTP request, itself, is something that can be done with a number of different libraries, including the builtin HttpURLConnection / URL classes, as well as third party libraries such as the Apache HttpComponents or the Google HTTP Java Client Library, the latter of which includes libraries for parsing common output formats, as well.

Enable resuming interrupt download in REST web service using Java

I am writing a REST web service for clients to download large data files. As part of this, I would like to implement a feature to enable resuming interrupt downloads in case an exception occurs or the connection is lost on the original request.
I did some research online and found that supporting Range/If-Range properties in the request header might be the solution, as indicated in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html.
My question are
In the scope of REST web service, is it the most commonly used and best practice to support Range/If-Range properties in the client HTTP request header, or just pass the byte offset as a query parameter in the client GET request, e.g., hostname:port/download?token=?byteoffset=??
If taking the former approach, on the server side, is there a standard way to handle request with Range field in JAX-RS specification (I am using Java)? The straightforward way is to just open an InputStream from the file and bypass the given # of bytes.
In general, don't use parameters that have to do with meta-information on the resource (or the part of it you need), so you should be using the Range, and keep sure the server allows that.
Note that, for example, byteoffset is not a meaningful part, component or semantically interesting bit of the resource itself, but a way of overcoming partial content (also, identical for all the resources, so you have to use the headers allowed for that, and hey! they're there for that).

Sending multiple files to a servlet with a single connection

I'm writing a Java desktop client which will send multiple files over the wire to a servlet using a post request. In the servlet I'm getting the input stream from the request to receive the files. The servlet will write the files to disk, one by one as they're read from the stream.
The implementation has a couple of requirements:
Only one HTTP request must be used to the server (so only a single stream)
The servlet must use a reasonable fixed amount of memory, no matter what the size of the files.
I had considered inserting markers into the stream so I know when one file ends and the next one begins. I'd then write some code to parse the stream in the servlet, and start writing the next file as appropriate.
Here's the thing... surely there's a library to do that. I've looked through apache commons and found nothing. Commons File Upload is interesting but since the upload comes from a Java app, not a browser it only solves the receiving end, not the sending.
Any ideas for a library which easily allows multiple file transfers across a single stream with fixed memory expectations even for very large files?
Thanks.
Just use HTTP multipart/form-data encoding on the POST request body. It's described in RFC-2388 and a standard way of uploading (multiple) files by HTTP.
You can do it with just java.net.URLConnection as described in this mini-tutorial, although it would generate lot of boilerplate code. A more convenienced approach would be using Apache Commons HttpClient.
In the servlet side you can then just use Apache Commons Fileupload to process the uploaded files the usual HTTP way (or when you're already on Servlet 3.0, the HttpServletRequest#getParts(), see also this answer for examples).

Categories