SpringBootはjarパッケージの配置を打って、Excelテンプレートはファイルをダウンロードします

5118 ワード

問題1.Resourceディレクトリの下のファイルを読み込むとパスが見つかりません


本機のテストは順調で、jarファイルをサーバーにパッケージしてテストしたとき、次のような異常情報が見つかりました.
java.nio.file.NoSuchFileException: file:/app.jar!/BOOT-INF/classes!/xxx.xlsx
理由:spring bootはプロジェクトをjarにパッケージ化し、java-jarパッケージ名を使用してサーバ上で実行します.この場合、ファイルはパッケージファイルなので、パスでファイルを取得できません.圧縮パッケージのファイルを読み込めないように、先に解凍する必要があります.結論:spring bootのファイルはストリームでしか読み取れません.
ストリームの読み取りは、以下の方法で行うことができる.
InputStream in = this.getClass().getClassLoader().getResourceAsStream("xxx.xlsx");

 


問題2.Excelテンプレートのダウンロードファイルが破損しています


本機のテストはすべて順調で、jarファイルを梱包してサーバーの上で置く時ダウンロードし終わってファイルを提示してファイルが破損します
質問原因分析:最初はresponseリクエスト応答ヘッダを修正したり、ByteArrayHttpMessageConverterを使用したり、ファイルの読み取り方法を修正したり、おべっかを使ったりするなど、さまざまな説を調べました.
後で別の文章を見て、mavenがパッケージ化する時、filterを使って、その原理はテキストファイルを処理して、そしてそれを変数に置き換えて、バイナリファイルに対して問題があって、参考https://www.jianshu.com/p/9d39745f6ce6;
この言い方に対して、私の実際の操作過程でjarパッケージの中のExcelファイルは正常なので、理論的にはこの問題ではありませんが!!!こう書いたら、スタティックリソースダウンロード方式OK、eclipseで実行するサービス、ファイル出力ストリーム方式を使ってもOK!!!
もちろん、穴がここまでで終わると、穴とは呼ばれません.問題が解決したと思って、アプリケーションをjarパッケージにして配置して、もう一度テストして、ニマ!!!この穴はまたTMが現れた!!!もう一度eclipseの下で検証して、やはりTMは正常で、再び梱包してから、穴は、まだそこにあって、動かないで、、、、
このような穴に出会って、本当にひざまずいて、幸いにも私はもう一つの予備案があって、だから、私はやっと浅くて、私の時間が限られていることを許して、根本的な問題の原因は私は位置付けの分析をしません.
最終的なソリューション:
  • シナリオ1:spring boot静的リソースを使用してダウンロードする方法;この方式ではインタフェースを定義する必要がなく、権限などの問題は制御できない.

  • リソースファイルをresource/staticディレクトリの下に置いて、サービスを起動して、IP:ポート/ファイルパスを使ってダウンロードすればいいです.このシナリオではpomファイルの下のresourceが必要です.filteringはfalseに設定し、jarに打った後も正常に使用できます.
     
            
                
                    src/main/resources
                    
                        **/*.*
                    
                    false    
                
                
                    src/main/webapp
                    
                        **/**
                    
                
                
            
        

     
  • シナリオ2:インタフェースを定義し、getClass()を使用する.getResourceAsStream方式でリソースを読み込み、ファイル出力ストリーム方式でダウンロードする.
  •     @GetMapping("/templateDownload")
        public Object templateDownload(HttpServletResponse response) {
            try {
                //      , jar , , 
                InputStream fis = FileUtil.getResourcesFileInputStream("temp/template.xlsx");
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                fis.close();
                response.setHeader("Content-Disposition", "attachment;filename=template.xlsx");
                //response.setContentType("application/zip");
                response.setContentType("application/binary;charset=ISO8859-1");
                ServletOutputStream out = response.getOutputStream();
                out.write(buffer);
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    public class FileUtil {
     
        public static InputStream getResourcesFileInputStream(String fileName) {
            return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
        }
    }

    この方法は大部分の人の問題が解決できるはずだが、一部の人はまだ解決できない.それは環境の問題だ.私はここでこの穴に出会って、この方法を使って、eclipseの下で正常で、jarパッケージに打った後、またTMファイルが破損して、
    作成したjarパッケージの中のリソースファイルをコピーして、開くのは正常で、ファイルのパッケージが正常であることを説明して、問題はファイルを読み取ることで、あるいは出力ストリームがファイルのあのブロックを書くことで、N多種の書き方を試して、N多配置を変えて、やはり解決していません;幸いなことに、前にデータのインポートとエクスポートをしたとき、似たような経験があったので、案3を考えました.
  • 方案三:インタフェースを定義し、ファイル出力ストリームの方式でダウンロードし、インタフェース実現過程、POIのWorkbook出力ストリームを使用する.

  • 結局POIは専門的で、Excelファイルの処理に対して根本的な理解があります;Excelテンプレートファイルによる.xlsと.xlsxタイプ、それぞれ指定して、XSSFWORkbookとHSSFWorkbookを使用すればいいです.ここではXSSFWORkbookを例に挙げて、リソースファイルをresourceディレクトリの下に置けばいいです.staticディレクトリを必要としません.
    public void templateDownload(HttpServletResponse response) {
            try {
                InputStream fis = FileUtil.getResourcesFileInputStream("static/temp/template.xlsx");
                XSSFWorkbook workbook = new XSSFWorkbook(fis);
                response.setContentType("application/binary;charset=ISO8859-1");
                String fileName = java.net.URLEncoder.encode("template", "UTF-8");
                response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xlsx");
                ServletOutputStream out = null;
                out = response.getOutputStream();
                workbook.write(out);
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 
            }
            return;
        }