簡體   English   中英

使用jax-rs從REST服務下載xml,而不在本地存儲文件

[英]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 ,只需將OutputStreamStreamingOutput#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();
    }
}

更新2

如果你還不知道,你可以簡單地返回你的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();

1.請參閱: 我是否需要Content-Type:application / octet-stream進行文件下載?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM