In a service, I am creating an XML document named doc and I want the user to receive a prompt to download the document without having to save it locally (like the one that says open or save the file).
However, I am not able to find how I should build the response that is going to be returned, or even what type to @produce.
So far I have this:
@GET
@Path("/getXML")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput getXML(
@FormParam("id") int id) {
UserDB userDao = new UserDB();
entities.User userd = userDao.getById(id);
DocumentBuilderFactory icFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder icBuilder;
try {
icBuilder = icFactory.newDocumentBuilder();
Document doc = icBuilder.newDocument();
Element rootElement = doc.createElement("Users");
doc.appendChild(rootElement);
rootElement.appendChild(getUser(doc, "1", "asd", "adas"));
rootElement.appendChild(getUser(doc, "2", "bbb", "ccc"));
//Here I should return the doc that is going to be downloaded
}
catch (Exception e) {
e.printStackTrace();
}
}
EDIT1: My main problem is that I cannot find how to build the response that is going to be returned. The answers that I have found download an already existing file that is locally stored.
The thread that is closest on answering is: How to make an XML document downloadable without intermediate file storage?
but I cannot understand how to apply it on my REST service response which differs from the HttpServletResponse.
If you look at the answer you linked to, you will see that a
StreamResult
is used. In the answer, aStringWriter
is passed to the constructor, but if you look at the Javadoc, it has an overloaded constructor that also takes anOutputStream
. So if you're returning aStreamingOutput
, just pass theOutputStream
from theStreamingOutput#write(OutputStream)
method to theStreamResult
constructor. Everything else from the answer should be the same.Here's the complete resource class I used to test. Notice that I use
@Produces(MediaType.APPLICATION_XML)
. There's no point in setting toapplication/octet-stream
if the data is XML1.Update
To automatically download the file (as opposed to displaying the XML result), we actually need to add the
Content-Disposition
header with theattachment
value. To do that, instead of returningStreamingOutput
from the method, we should returnResponse
, where the entity will be theStreamingOutput
Update 2
If you don't already know, you can simply return your POJOs (or list of them) and they will automatically get serialized to XML. You don't need to manually use the DOM classes to create XML structure. There are already Entity Providers that will handle the conversion from POJO to XML for us. For example, if we have the following POJO (needs to be annotated with
@XmlRootElement
)then we can just return it and it will automatically be serialized to
Here's an example
It's a lot less messy isn't it? If you want to return a list of Users, then you need to wrap it in
GenericEntity
1. See: Do I need Content-Type: application/octet-stream for file download?