How to download existed xlsx file from jar in java

1.9k Views Asked by At

I put Excel file in resources/template/a.xlsx, i package it with mvn package, i want to and a API to download a.xlsx from this jar.

My API:

public void downloadExcelTemplate(RoutingContext routingContext) {

        String fileName = "a.xlsx";
        String path = "template" + File.separator+fileName;

        HttpServerResponse response = routingContext.response();
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream(path)));
            StringBuffer buffer = new StringBuffer();
            String line = "";
            while ((line = in.readLine()) != null){
                buffer.append(line);
            }
            response.putHeader("content-type", "application/octet-stream;charset=UTF-8");

            response.putHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), StandardCharsets.ISO_8859_1));
            response.putHeader("Pragma", "no-cache");
            response.putHeader("Cache-Control", "no-cache");
            response.setChunked(true);
            response.write(buffer.toString());
        } catch (IOException e) {
            logger.error("error: ", e);
        }
        response.end();
    }

I use vertx.web and Spring, poi dependency is:

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17-beta1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17-beta1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-excelant</artifactId>
            <version>3.17-beta1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.17-beta1</version>
        </dependency>

I think SpringMVC and vertx.web is same in download, but when i try to download, the download xlsx file couldn't be open.

3

There are 3 best solutions below

1
On BEST ANSWER

DO NOT in this case USE java.io.Reader for this!

xlsx files are binary (technically they're zip files).

Using Reader will corrupt the data

public void downloadExcelTemplate(RoutingContext routingContext) {

        String fileName = "a.xlsx";
        String path = "template" + File.separator+fileName;

        HttpServerResponse response = routingContext.response();
        try(final InputStream inputStream = 
                this.getClass().getClassLoader().getResourceAsStream(path);
            final BufferedInputStream in =
                new BufferedInputStream(inputStream); ) {
            // Use the actual content type for the file
            response.putHeader("content-type", 
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

            response.putHeader("Content-Disposition", 
                 "attachment;filename=" + 
                   new String(fileName.getBytes(), StandardCharsets.ISO_8859_1));
            response.putHeader("Pragma", "no-cache");
            response.putHeader("Cache-Control", "no-cache");
            response.setChunked(true);

            // Vert.x Buffer Object
            Buffer buffer = Buffer.buffer()
            byte[] rawBuffer = new byte[1024];
            int numRead;
            while((numRead = is.read(rawBuffer, 0, rawBuffer.length)) != -1) {
                response.appendBytes(rawBuffer, 0, numRead);
            }
            response.write(buffer);
        } catch (IOException e) {
            logger.error("error: ", e);
        }
        response.end();
    }
}
0
On

Resource paths are case-sensitive and use a slash (/) as path separator.

The response is a binary file, not a text. Hence it must loaded by an InputStream, and written by an OutputStream. Readers and Writers are for Unicode text and always imply a charset conversion for the binary bytes. Which would corrupt things or at least make them slow.

public void downloadExcelTemplate(RoutingContext routingContext) {

    String fileName = "a.xlsx";
    String path = "template/" + fileName;

    HttpServerResponse response = routingContext.response();
    try {
        URL url = getClass().getClassLoader().getResource(path);
        Path path = Paths.get(url.toURI());

        response.putHeader("Content-Type", "application/octet-stream;charset=UTF-8");
        response.putHeader("Content-Disposition",
            "attachment;filename=" + URLEncoder.encode(fileName,"ISO-8859-1"));
        response.putHeader("Pragma", "no-cache");
        response.putHeader("Cache-Control", "no-cache");
        response.setChunked(true);

        // It would have been nice to do just: Files.copy(path, response.getOutputStream());
        byte[] content = Files.readAllBytes(path);
        Buffer buffer = Buffer.buffer(content);
        response.write(buffer);
    } catch (IOException e) {
        logger.error("error: ", e);
    }
    response.end();
}

Not sure what the effect is of ";charset=UTF-8" for the content type. That Excel internally uses UTF-8? Should not be needed.

0
On

Nice to reply to you. First, you ought to consider the MVN package to a jar lead to your excel that can not open.

Then, you can try another source path to access.

Finally, you can try to movie the excel at the jar's same file directory to access. I think that is OK. My best to you. Allen