如何从 Java 的 jar 文件中下载已存在的 xlsx 文件

huangapple go评论65阅读模式
英文:

How to download existed xlsx file from jar in java

问题

我将Excel文件放在resources/template/a.xlsx中,然后使用mvn package进行打包,我想要添加一个API来从这个jar包中下载a.xlsx

我的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();
    }

我使用了vertx.webSpringpoi的依赖如下:

<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>

我认为在下载方面,SpringMVC和vertx.web是相同的,但当我尝试下载时,下载的xlsx文件无法打开。

英文:

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 = &quot;a.xlsx&quot;;
        String path = &quot;template&quot; + 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 = &quot;&quot;;
            while ((line = in.readLine()) != null){
                buffer.append(line);
            }
            response.putHeader(&quot;content-type&quot;, &quot;application/octet-stream;charset=UTF-8&quot;);

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

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

&lt;dependency&gt;
            &lt;groupId&gt;org.apache.poi&lt;/groupId&gt;
            &lt;artifactId&gt;poi&lt;/artifactId&gt;
            &lt;version&gt;3.17&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.poi&lt;/groupId&gt;
            &lt;artifactId&gt;poi-ooxml-schemas&lt;/artifactId&gt;
            &lt;version&gt;3.17-beta1&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.poi&lt;/groupId&gt;
            &lt;artifactId&gt;poi-ooxml&lt;/artifactId&gt;
            &lt;version&gt;3.17-beta1&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.poi&lt;/groupId&gt;
            &lt;artifactId&gt;poi-excelant&lt;/artifactId&gt;
            &lt;version&gt;3.17-beta1&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.poi&lt;/groupId&gt;
            &lt;artifactId&gt;poi-scratchpad&lt;/artifactId&gt;
            &lt;version&gt;3.17-beta1&lt;/version&gt;
        &lt;/dependency&gt;

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

答案1

得分: 2

    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); ) {
                // 使用文件的实际内容类型
                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 buffer = Buffer.buffer();
                byte[] rawBuffer = new byte[1024];
                int numRead;
                while((numRead = in.read(rawBuffer, 0, rawBuffer.length)) != -1) {
                    buffer.appendBytes(rawBuffer, 0, numRead);
                }
                response.write(buffer);
            } catch (IOException e) {
                logger.error("error: ", e);
            }
            response.end();
        }
    }
英文:

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 = &quot;a.xlsx&quot;;
String path = &quot;template&quot; + 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(&quot;content-type&quot;, 
&quot;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&quot;);
response.putHeader(&quot;Content-Disposition&quot;, 
&quot;attachment;filename=&quot; + 
new String(fileName.getBytes(), StandardCharsets.ISO_8859_1));
response.putHeader(&quot;Pragma&quot;, &quot;no-cache&quot;);
response.putHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;);
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(&quot;error: &quot;, e);
}
response.end();
}
}

答案2

得分: 1

资源路径区分大小写,并使用斜杠(/)作为路径分隔符。

响应是一个二进制文件,而不是文本。因此必须使用InputStream加载它,并使用OutputStream写入它。读取器(Readers)和写入器(Writers)用于Unicode文本,并且总是暗示对二进制字节进行字符集转换。这可能会破坏文件或至少使其变慢。

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 filePath = 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);

        // 希望能够只写:Files.copy(filePath, response.getOutputStream());
        byte[] content = Files.readAllBytes(filePath);
        Buffer buffer = Buffer.buffer(content);
        response.write(buffer);
    } catch (IOException | URISyntaxException e) {
        logger.error("error: ", e);
    }
    response.end();
}

不确定在内容类型中使用";charset=UTF-8"的影响是什么。Excel内部使用UTF-8吗?应该不是必需的。

英文:

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 = &quot;a.xlsx&quot;;
String path = &quot;template/&quot; + fileName;
HttpServerResponse response = routingContext.response();
try {
URL url = getClass().getClassLoader().getResource(path);
Path path = Paths.get(url.toURI());
response.putHeader(&quot;Content-Type&quot;, &quot;application/octet-stream;charset=UTF-8&quot;);
response.putHeader(&quot;Content-Disposition&quot;,
&quot;attachment;filename=&quot; + URLEncoder.encode(fileName,&quot;ISO-8859-1&quot;));
response.putHeader(&quot;Pragma&quot;, &quot;no-cache&quot;);
response.putHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;);
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(&quot;error: &quot;, 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.

答案3

得分: -1

很高兴回复你。
首先,你应该考虑将MVN包转换为一个jar文件,导致你的Excel无法打开。
然后,你可以尝试另一个源路径来访问。
最后,你可以尝试将Excel文件移动到jar文件相同的目录中进行访问。我认为那样应该可以。
祝你一切顺利。艾伦

英文:

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

huangapple
  • 本文由 发表于 2020年10月19日 18:21:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64425407.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定