[英]Download xml from REST service using jax-rs without locally storing the file
在一項服務中,我正在創建一個名為doc的XML文檔,我希望用戶能夠收到下載文檔的提示,而無需在本地保存(如打開或保存文件的那個)。
但是,我無法找到如何構建將要返回的響應,甚至是@produce的類型。
到目前為止我有這個:
@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();
}
}
編輯1:我的主要問題是我找不到如何構建將要返回的響應。 我找到的答案是下載本地存儲的現有文件。
最接近回答的主題是: 如何在沒有中間文件存儲的情況下下載XML文檔?
但我無法理解如何將其應用於我的REST服務響應,該響應與HttpServletResponse不同。
如果您查看鏈接的答案,您將看到使用StreamResult
。 在答案中, StringWriter
被傳遞給構造函數,但是如果你看一下Javadoc,它有一個重載的構造函數,它也接受一個OutputStream
。 因此,如果您要返回StreamingOutput
,只需將OutputStream
從StreamingOutput#write(OutputStream)
方法傳遞給StreamResult
構造函數。 答案中的其他所有內容都應該相同。
return new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(out);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
};
這是我用來測試的完整資源類。 請注意,我使用@Produces(MediaType.APPLICATION_XML)
。 如果數據是XML 1 ,則設置為application/octet-stream
沒有意義。
@Path("dom")
public class DomXmlResource {
@GET
@Produces(MediaType.APPLICATION_XML)
public StreamingOutput getXml() throws Exception {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("company");
doc.appendChild(rootElement);
Element staff = doc.createElement("Staff");
rootElement.appendChild(staff);
staff.setAttribute("id", "1");
Element firstname = doc.createElement("firstname");
firstname.appendChild(doc.createTextNode("yong"));
staff.appendChild(firstname);
return new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
try {
Transformer transformer = TransformerFactory.newInstance()
.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StreamResult result = new StreamResult(out);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
}
要自動下載文件(而不是顯示XML結果),我們實際上需要添加帶有attachment
值的Content-Disposition
標頭。 要做到這一點,我們應該返回Response
,而不是從方法返回StreamingOutput
,實體將是StreamingOutput
@Path("dom")
public class DomXmlResource {
@GET
@Produces(MediaType.APPLICATION_XML)
public Response getXml() throws Exception {
...
StreamingOutput entity = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
...
}
};
return Response.ok(entity)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=file.xml")
.build();
}
}
如果你還不知道,你可以簡單地返回你的POJO(或它們的列表),它們將自動被序列化為XML。 您無需手動使用DOM類來創建XML結構。 已經有實體提供商將為我們處理從POJO到XML的轉換。 例如,如果我們有以下POJO(需要使用@XmlRootElement
注釋)
@XmlRootElement
public class User {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
然后我們可以返回它,它會自動被序列化
<user><name>footer</name></user>
這是一個例子
@Path("pojo")
public class PojoXmlResource {
@GET
@Produces("application/xml")
public Response getXml() {
User user = new User();
user.setName("Jane Doe");
return Response.ok(user)
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=user.xml")
.build();
}
}
這不是很麻煩不是嗎? 如果要返回用戶列表,則需要將其包裝在GenericEntity
List<User> users = Arrays.asList(user1, user2, user3);
GenericEntity<List<User>> entity = new GenericEntity<List<User>>(users){};
return Response.ok(entity)
...
.build();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.