代码之家  ›  专栏  ›  技术社区  ›  Tauren

使用JERSEY的输入和输出二进制流?

  •  108
  • Tauren  · 技术社区  · 15 年前

    我使用Jersey实现了一个RESTful API,主要用于检索和服务JSON编码的数据。但在某些情况下,我需要完成以下任务:

    • 导出可下载的文档,如PDF、XLS、ZIP或其他二进制文件。
    • 检索多部分数据,例如一些JSON和上载的XLS文件

    我有一个基于JQuery的单页web客户机,它创建对该web服务的AJAX调用。目前,它不做表单提交,而是使用GET和POST(带有JSON对象)。我应该使用表单post发送数据和附加的二进制文件,还是可以使用JSON加二进制文件创建多部分请求?

    我一直在查看Jersey附带的样本,但还没有找到任何能够说明如何执行这两项操作的内容。如果有关系的话,我会用Jersey和Jackson做Object->JSON没有XML步骤,我没有真正利用JAX-RS。

    10 回复  |  直到 15 年前
        1
  •  109
  •   Buhake Sindi Tesnep    10 年前

    我通过扩展 StreamingOutput 对象以下是一些示例代码:

    @Path("PDF-file.pdf/")
    @GET
    @Produces({"application/pdf"})
    public StreamingOutput getPDF() throws Exception {
        return new StreamingOutput() {
            public void write(OutputStream output) throws IOException, WebApplicationException {
                try {
                    PDFGenerator generator = new PDFGenerator(getEntity());
                    generator.generatePDF(output);
                } catch (Exception e) {
                    throw new WebApplicationException(e);
                }
            }
        };
    }
    

        2
  •  30
  •   Community Mohan Dere    14 年前

    我必须返回一个rtf文件,这对我很有效。

    // create a byte array of the file in correct format
    byte[] docStream = createDoc(fragments); 
    
    return Response
                .ok(docStream, MediaType.APPLICATION_OCTET_STREAM)
                .header("content-disposition","attachment; filename = doc.rtf")
                .build();
    
        3
  •  23
  •   Grégory    14 年前

    我使用这段代码将泽西岛的excel(xlsx)文件(ApachePOI)作为附件导出。

    @GET
    @Path("/{id}/contributions/excel")
    @Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
    public Response exportExcel(@PathParam("id") Long id)  throws Exception  {
    
        Resource resource = new ClassPathResource("/xls/template.xlsx");
    
        final InputStream inp = resource.getInputStream();
        final Workbook wb = WorkbookFactory.create(inp);
        Sheet sheet = wb.getSheetAt(0);
    
        Row row = CellUtil.getRow(7, sheet);
        Cell cell = CellUtil.getCell(row, 0);
        cell.setCellValue("TITRE TEST");
    
        [...]
    
        StreamingOutput stream = new StreamingOutput() {
            public void write(OutputStream output) throws IOException, WebApplicationException {
                try {
                    wb.write(output);
                } catch (Exception e) {
                    throw new WebApplicationException(e);
                }
            }
        };
    
    
        return Response.ok(stream).header("content-disposition","attachment; filename = export.xlsx").build();
    
    }
    
        4
  •  15
  •   Hank Jesus M C    13 年前

    这是另一个例子。我正在通过 ByteArrayOutputStream . 资源返回一个 Response 对象,流的数据就是实体。

    为了说明响应代码的处理,我添加了缓存头的处理( If-modified-since , If-none-matches 等)。

    @Path("{externalId}.png")
    @GET
    @Produces({"image/png"})
    public Response getAsImage(@PathParam("externalId") String externalId, 
            @Context Request request) throws WebApplicationException {
    
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        // do something with externalId, maybe retrieve an object from the
        // db, then calculate data, size, expirationTimestamp, etc
    
        try {
            // create a QRCode as PNG from data     
            BitMatrix bitMatrix = new QRCodeWriter().encode(
                    data, 
                    BarcodeFormat.QR_CODE, 
                    size, 
                    size
            );
            MatrixToImageWriter.writeToStream(bitMatrix, "png", stream);
    
        } catch (Exception e) {
            // ExceptionMapper will return HTTP 500 
            throw new WebApplicationException("Something went wrong …")
        }
    
        CacheControl cc = new CacheControl();
        cc.setNoTransform(true);
        cc.setMustRevalidate(false);
        cc.setNoCache(false);
        cc.setMaxAge(3600);
    
        EntityTag etag = new EntityTag(HelperBean.md5(data));
    
        Response.ResponseBuilder responseBuilder = request.evaluatePreconditions(
                updateTimestamp,
                etag
        );
        if (responseBuilder != null) {
            // Preconditions are not met, returning HTTP 304 'not-modified'
            return responseBuilder
                    .cacheControl(cc)
                    .build();
        }
    
        Response response = Response
                .ok()
                .cacheControl(cc)
                .tag(etag)
                .lastModified(updateTimestamp)
                .expires(expirationTimestamp)
                .type("image/png")
                .entity(stream.toByteArray())
                .build();
        return response;
    }   
    

    stream.toByteArray() 是一个没有记忆的智慧:)它适用于我的<1KB PNG文件。。。

        5
  •  14
  •   Daniel Szalay    12 年前

    FileStreamingOutput

    public class FileStreamingOutput implements StreamingOutput {
    
        private File file;
    
        public FileStreamingOutput(File file) {
            this.file = file;
        }
    
        @Override
        public void write(OutputStream output)
                throws IOException, WebApplicationException {
            FileInputStream input = new FileInputStream(file);
            try {
                int bytes;
                while ((bytes = input.read()) != -1) {
                    output.write(bytes);
                }
            } catch (Exception e) {
                throw new WebApplicationException(e);
            } finally {
                if (output != null) output.close();
                if (input != null) input.close();
            }
        }
    
    }
    

    GET

    @GET
    @Produces("application/pdf")
    public StreamingOutput getPdf(@QueryParam(value="name") String pdfFileName) {
        if (pdfFileName == null)
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        if (!pdfFileName.endsWith(".pdf")) pdfFileName = pdfFileName + ".pdf";
    
        File pdf = new File(Settings.basePath, pdfFileName);
        if (!pdf.exists())
            throw new WebApplicationException(Response.Status.NOT_FOUND);
    
        return new FileStreamingOutput(pdf);
    }
    

    和客户,如果您需要:

    Client

    private WebResource resource;
    
    public InputStream getPDFStream(String filename) throws IOException {
        ClientResponse response = resource.path("pdf").queryParam("name", filename)
            .type("application/pdf").get(ClientResponse.class);
        return response.getEntityInputStream();
    }
    
        6
  •  7
  •   Jaime Casero    11 年前

    此示例演示如何通过rest资源在JBoss中发布日志文件。注意get方法使用StreamingOutput接口来流式传输日志文件的内容。

    @Path("/logs/")
    @RequestScoped
    public class LogResource {
    
    private static final Logger logger = Logger.getLogger(LogResource.class.getName());
    @Context
    private UriInfo uriInfo;
    private static final String LOG_PATH = "jboss.server.log.dir";
    
    public void pipe(InputStream is, OutputStream os) throws IOException {
        int n;
        byte[] buffer = new byte[1024];
        while ((n = is.read(buffer)) > -1) {
            os.write(buffer, 0, n);   // Don't allow any extra bytes to creep in, final write
        }
        os.close();
    }
    
    @GET
    @Path("{logFile}")
    @Produces("text/plain")
    public Response getLogFile(@PathParam("logFile") String logFile) throws URISyntaxException {
        String logDirPath = System.getProperty(LOG_PATH);
        try {
            File f = new File(logDirPath + "/" + logFile);
            final FileInputStream fStream = new FileInputStream(f);
            StreamingOutput stream = new StreamingOutput() {
                @Override
                public void write(OutputStream output) throws IOException, WebApplicationException {
                    try {
                        pipe(fStream, output);
                    } catch (Exception e) {
                        throw new WebApplicationException(e);
                    }
                }
            };
            return Response.ok(stream).build();
        } catch (Exception e) {
            return Response.status(Response.Status.CONFLICT).build();
        }
    }
    
    @POST
    @Path("{logFile}")
    public Response flushLogFile(@PathParam("logFile") String logFile) throws URISyntaxException {
        String logDirPath = System.getProperty(LOG_PATH);
        try {
            File file = new File(logDirPath + "/" + logFile);
            PrintWriter writer = new PrintWriter(file);
            writer.print("");
            writer.close();
            return Response.ok().build();
        } catch (Exception e) {
            return Response.status(Response.Status.CONFLICT).build();
        }
    }    
    

        7
  •  7
  •   orangegiraffa    11 年前

    使用Jersey 2.16文件下载非常简单。

    下面是ZIP文件的示例

    @GET
    @Path("zipFile")
    @Produces("application/zip")
    public Response getFile() {
        File f = new File(ZIP_FILE_PATH);
    
        if (!f.exists()) {
            throw new WebApplicationException(404);
        }
    
        return Response.ok(f)
                .header("Content-Disposition",
                        "attachment; filename=server.zip").build();
    }
    
        8
  •  5
  •   Dovev Hefetz    14 年前

    我发现以下内容对我很有帮助,我想与大家分享一下,以防对你或其他人有所帮助。我想要像MediaType.PDF_TYPE这样的东西,它不存在,但这段代码做的是相同的事情:

    DefaultMediaTypePredictor.CommonMediaTypes.
            getMediaTypeFromFileName("anything.pdf")
    

    看见 http://jersey.java.net/nonav/apidocs/1.1.0-ea/contribs/jersey-multipart/com/sun/jersey/multipart/file/DefaultMediaTypePredictor.CommonMediaTypes.html

    就我而言,我在另一个网站上发布了一份PDF文档:

    FormDataMultiPart p = new FormDataMultiPart();
    p.bodyPart(new FormDataBodyPart(FormDataContentDisposition
            .name("fieldKey").fileName("document.pdf").build(),
            new File("path/to/document.pdf"),
            DefaultMediaTypePredictor.CommonMediaTypes
                    .getMediaTypeFromFileName("document.pdf")));
    

    http://jersey.576304.n2.nabble.com/Multipart-Post-td4252846.html

        9
  •  4
  •   Muqsith    13 年前

    这对我很管用 http://example.com/rest/muqsith/get-file?filePath=C :\Users\I066807\Desktop\test.xml

    @GET
    @Produces({ MediaType.APPLICATION_OCTET_STREAM })
    @Path("/get-file")
    public Response getFile(@Context HttpServletRequest request){
       String filePath = request.getParameter("filePath");
       if(filePath != null && !"".equals(filePath)){
            File file = new File(filePath);
            StreamingOutput stream = null;
            try {
            final InputStream in = new FileInputStream(file);
            stream = new StreamingOutput() {
                public void write(OutputStream out) throws IOException, WebApplicationException {
                    try {
                        int read = 0;
                            byte[] bytes = new byte[1024];
    
                            while ((read = in.read(bytes)) != -1) {
                                out.write(bytes, 0, read);
                            }
                    } catch (Exception e) {
                        throw new WebApplicationException(e);
                    }
                }
            };
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
            return Response.ok(stream).header("content-disposition","attachment; filename = "+file.getName()).build();
            }
        return Response.ok("file path null").build();
    }
    
        10
  •  1
  •   Community Mohan Dere    8 年前

    另一个示例代码,您可以将文件上载到REST服务,REST服务将文件压缩,客户端从服务器下载zip文件。

    https://stackoverflow.com/a/32253028/15789

    推荐文章