Java 使用 JERSEY 的输入和输出二进制流?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3496209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Input and Output binary streams using JERSEY?
提问by Tauren
I'm using Jersey to implement a RESTful API that is primarily retrieve and serve JSON encoded data. But I have some situations where I need to accomplish the following:
我正在使用 Jersey 来实现一个主要用于检索和提供 JSON 编码数据的 RESTful API。但是我在某些情况下需要完成以下操作:
- Export downloadable documents, such as PDF, XLS, ZIP, or other binary files.
- Retrieve multipart data, such some JSON plus an uploaded XLS file
- 导出可下载的文档,例如 PDF、XLS、ZIP 或其他二进制文件。
- 检索多部分数据,例如一些 JSON 加上上传的 XLS 文件
I have a single-page JQuery-based web client that creates AJAX calls to this web service. At the moment, it doesn't do form submits, and uses GET and POST (with a JSON object). Should I utilize a form post to send data and an attached binary file, or can I create a multipart request with JSON plus binary file?
我有一个基于 JQuery 的单页 Web 客户端,它创建对此 Web 服务的 AJAX 调用。目前,它不执行表单提交,而是使用 GET 和 POST(使用 JSON 对象)。我应该使用表单发布来发送数据和附加的二进制文件,还是可以使用 JSON 和二进制文件创建多部分请求?
My application's service layer currently creates a ByteArrayOutputStream when it generates a PDF file. What is the best way to output this stream to the client via Jersey? I've created a MessageBodyWriter, but I don't know how to use it from a Jersey resource. Is that the right approach?
我的应用程序的服务层在生成 PDF 文件时当前会创建一个 ByteArrayOutputStream。通过 Jersey 将此流输出到客户端的最佳方法是什么?我创建了一个 MessageBodyWriter,但我不知道如何从 Jersey 资源中使用它。这是正确的方法吗?
I've been looking through the samples included with Jersey, but haven't found anything yet that illustrates how to do either of these things. If it matters, I'm using Jersey with Hymanson to do Object->JSON without the XML step and am not really utilizing JAX-RS.
我一直在查看 Jersey 中包含的示例,但还没有找到任何说明如何执行这些操作的任何内容。如果重要的话,我正在使用 Jersey 和 Hymanson 来执行 Object->JSON 而没有 XML 步骤,并且并没有真正使用 JAX-RS。
回答by MikeTheReader
I managed to get a ZIP file or a PDF file by extending the StreamingOutput
object. Here is some sample code:
我设法通过扩展StreamingOutput
对象来获得 ZIP 文件或 PDF 文件。下面是一些示例代码:
@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);
}
}
};
}
The PDFGenerator class (my own class for creating the PDF) takes the output stream from the write method and writes to that instead of a newly created output stream.
PDFGenerator 类(我自己的用于创建 PDF 的类)从 write 方法获取输出流并写入该输出流,而不是新创建的输出流。
Don't know if it's the best way to do it, but it works.
不知道这是否是最好的方法,但它有效。
回答by Abhishek Rakshit
I had to return a rtf file and this worked for me.
我不得不返回一个 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();
回答by Dovev Hefetz
I found the following helpful to me and I wanted to share in case it helps you or someone else. I wanted something like MediaType.PDF_TYPE, which doesn't exist, but this code does the same thing:
我发现以下内容对我有帮助,我想分享一下,以防它对您或其他人有所帮助。我想要像 MediaType.PDF_TYPE 这样的东西,它不存在,但这段代码做同样的事情:
DefaultMediaTypePredictor.CommonMediaTypes.
getMediaTypeFromFileName("anything.pdf")
In my case I was posting a PDF document to another site:
就我而言,我将 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")));
Then p gets passed as the second parameter to post().
然后 p 作为第二个参数传递给 post()。
This link was helpful to me in putting this code snippet together: http://jersey.576304.n2.nabble.com/Multipart-Post-td4252846.html
这个链接对我把这个代码片段放在一起很有帮助:http: //jersey.576304.n2.nabble.com/Multipart-Post-td4252846.html
回答by Grégory
I'm using this code to export excel (xlsx) file ( Apache Poi ) in jersey as an attachement.
我正在使用此代码将球衣中的 excel (xlsx) 文件 (Apache Poi) 作为附件导出。
@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();
}
回答by Hank
Here's another example. I'm creating a QRCode as a PNG via a ByteArrayOutputStream
. The resource returns a Response
object, and the stream's data is the entity.
这是另一个例子。我正在通过 ByteArrayOutputStream
. 资源返回一个Response
对象,流的数据就是实体。
To illustrate the response code handling, I've added handling of cache headers (If-modified-since
, If-none-matches
, etc).
为了说明响应代码处理,我已经添加了处理缓存头(的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;
}
Please don't beat me up in case stream.toByteArray()
is a no-no memory wise :) It works for my <1KB PNG files...
请不要殴打我,以防万一stream.toByteArray()
是无记忆的:) 它适用于我的 <1KB PNG 文件...
回答by Muqsith
This worked fine with me url:http://example.com/rest/muqsith/get-file?filePath=C:\Users\I066807\Desktop\test.xml
这对我来说很好用 url: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();
}
回答by Jaime Casero
This example shows how to publish log files in JBoss through a rest resource. Note the get method uses the StreamingOutput interface to stream the content of the log file.
这个例子展示了如何通过一个剩余资源在 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();
}
}
}
}
回答by Daniel Szalay
I have been composing my Jersey 1.17 services the following way:
我一直在按以下方式编写 Jersey 1.17 服务:
FileStreamingOutput
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
@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);
}
And the client, if you need it:
和客户端,如果你需要它:
Client
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();
}
回答by orangegiraffa
Using Jersey 2.16 File download is very easy.
使用 Jersey 2.16 文件下载非常简单。
Below is the example for the ZIP file
以下是 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();
}
回答by RuntimeException
Another sample code where you can upload a file to the REST service, the REST service zips the file, and the client downloads the zip file from the server. This is a good example of using binary input and output streams using Jersey.
另一个示例代码,您可以在其中将文件上传到 REST 服务,REST 服务压缩文件,然后客户端从服务器下载 zip 文件。这是使用 Jersey 使用二进制输入和输出流的一个很好的例子。
https://stackoverflow.com/a/32253028/15789
https://stackoverflow.com/a/32253028/15789
This answer was posted by me in another thread. Hope this helps.
这个答案是我在另一个帖子中发布的。希望这可以帮助。