Home » Java » java – Setting multiple images to the response entity-Exceptionshub

java – Setting multiple images to the response entity-Exceptionshub

Posted by: admin February 25, 2020 Leave a comment

Questions:

I want to return response with multiple images to client. And in client side i want to download those images. I haven’t find any method like .setEntity() for HttpServletResponse. So i have decided to add images in header fields. I am adding in following way,

File sourceFile = new File(serverLocation + "/" + filename);

servletresponse.setContentType(new MimetypesFileTypeMap().getContentType(sourceFile));
servletresponse.setContentLength((int)sourceFile.length());
servletresponse.setHeader(filename, "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"));

I am unable to download on client side. This is what i am doing on client side,

CloseableHttpResponse response = httpclient.execute(httppost);
Header[] headers = response.getAllHeaders();
            for (int i = 0; i < headers.length; i++) {
                if (headers[i].getName().equals(filename)) {
                    imagename = headers[i].getValue();
                }
            }
InputStream fileInputStream = new ByteArrayInputStream(imagename.getBytes(StandardCharsets.UTF_8));
            byte[] bufffer = new byte[512];
            while ((bufferSize = fileInputStream.read(bufffer)) > 0) {
                fileOutputStream.write(bufffer, 0, bufferSize);
            }

However its not writing images. How can i add multiple files and download it on client side. Please help.

How to&Answers:

A single HTTP call can only return a single image(content). If you need to send over multiple images you could possibly:

  1. Pass on image URLs in response instead of the actual resource and have client parse and download them
  2. If you want to hide the response from the body you can use headers for the same purpose as you mentioned in the example (but that looks like a weird use case to me)

Answer:

  • A file name is not an image. It’s just the text that identifies the file.
  • The contents of the file is a sequence of bytes which is entirely separate from the name. This is the actual image data.

Sending the file name in the response will not send the contents.

There are two common ways to send multiple images in an HTTP response:

  1. Send an archive containing multiple files, such as a zip file.
  2. Send a response whose content type is multipart/mixed, as described in RFC 2046. You can do this manually, but the classes of the javax.mail.internet package make it a lot easier.

Both approaches require the images to be in the response body, not in the headers. Headers are only intended for (relatively) short strings, and header names have restrictions on which characters they may contain.

The zip file approach is the easiest to code:

String[] filenames = { /* ... */ };

servletresponse.setContentType("application/zip");

try (ZipOutputStream zip = new ZipOutputStream(
    servletresponse.getOutputStream())) {

    for (String filename : filenames) {
        ZipEntry entry = new ZipEntry(filename);
        zip.putNextEntry(entry);
        Files.copy(Paths.get(filename), zip);
    }
}

The second approach requires the JavaMail API, and the Java Activation Framework API. If you are running in a true Java EE server like GlassFish or JBoss, you have access to them already, since JavaMail and JAF are components required by the Java EE specification.

String[] filenames = { /* ... */ };

MimeMultipart multipart = new MimeMultipart("mixed");

for (String filename : filenames) {
    MimeBodyPart part = new MimeBodyPart();
    part.attachFile(filename, null, "base64");
    multipart.addBodyPart(part);
}

Properties props = new Properties();
Session session = Session.getDefaultInstance(props);
MimeMessage message = new MimeMessage(session);
message.setContent(multipart);
message.saveChanges();

servletresponse.setContentType(multipart.getContentType());
try (OutputStream out = servletresponse.getOutputStream()) {
    multipart.writeTo(out);
}

Each approach will require different handling on the client side. The client can just save the zip archive directly:

String home = System.getProperty("user.home");

try (InputStream content = response.getEntity().getContent()) {
    Files.copy(content, Paths.get(home, "Downloads", "images.zip"));
}

Or, of course, you can use ZipInputStream to read the entries in the zip archive, and save each zip entry to a file whose name matches the zip entry name.

The multipart response would require an API capable of reading a MIME multipart message. JavaMail and JAF are one such option.