

JAX-RSを使って、ファイルをダウンロードできるWebAPIを作っています。  
このファイルは、ダウンロードが終わったら即時削除したいのですが、その方法が分かりません。

[code]

    @GET
    @Path("download")
    public Response download() {
    
        ...
    
        try (val is = Files.newInputStream(fileInfo.getPath(), StandardOpenOption.DELETE_ON_CLOSE)) {
            val response = Response.ok(is, fileInfo.getMimeType()).encoding("UTF-8")
                    .header("Content-Disposition", contentDisposition(fileInfo)).build();
            return response;
        }
    }
    
[/code]

例えばこのように作ってみると、`ClosedChannelException`が発生してしまいます。  
恐らく、このメソッド（というかtry句）を抜けた時点でcloseされ、ファイルが削除されますので、そのあとJAX-
RSがHTTPクライアントにファイルのバイナリを流そうとして失敗しているのだと思います。

何か良い方法は無いでしょうか？


CC BY-SA 3.0
2017-12-12T01:38:42.807
40201
2018-02-20T13:00:09.140
8078
question
java java-ee
ダウンロードされたファイルを削除したい


ダウンロードが完了したことは検知できないので、ファイルサイズが小さければ、ByteArrayInputStreamに変換した後に、ファイルを削除してはいかがでしょうか？

ファイルが作られるタイミングがわかりませんが、そもそもファイルを作らずに、直接ストリームにデータを流す事を考慮した方が良いのではないかと思います。


CC BY-SA 3.0
2018-02-20T06:58:52.700
41865
2018-02-20T06:58:52.700
27467
40201
answer


出力済みのファイルをダウンロードしなければならない何かしらの理由(ファイルが外部コマンドで生成されるとか)がないのであれば、そもそもファイルを作らずに直接ストリームにデータを流す方がよいかと思います。

何かしらの理由があるのであれば、 StreamingOutput を作成して、Response を作成し、ダウンロードさせ、出力完了後に
File#delete() でファイルを削除する方法で期待通り動くかもしれません。

[code]

    package com.example;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.nio.file.Files;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.StreamingOutput;
    
    @Path("download")
    public class FileDownload {
    
        /**
         * CSV ファイルを一時ファイルに書き出してダウンロード。 ダウンロード完了後に一時ファイルを削除する。
         *
         * @return
         * @throws IOException
         */
        @GET
        @Path("csvfromfile")
        @Produces("text/plain")
        public Response downloadCsvFromFile() throws IOException {
            System.out.println("Hello!");
    
            // output temp csv file
            File tmpFile = File.createTempFile("download", ".csv");
            System.out.printf("tmpFile => %s\n", tmpFile);
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF-8"))) {
    
                int lineNumber = 0;
                while (lineNumber < 10000) {
                    lineNumber++;
                    writer.write(String.format("%06d", lineNumber));
                    writer.newLine();
                }
                writer.flush();
            }
    
            // StreamingOutput を作成
            StreamingOutput stream = (OutputStream out) -> {
                Files.copy(tmpFile.toPath(), out);
                System.out.printf("try to delete tmpFile(%s),\n", tmpFile);
                boolean deleteOk = tmpFile.delete();
                System.out.printf("delete tmpFile(%s) is %b!\n", tmpFile, deleteOk);
            };
    
            // StreamingOutput をもとに Response を作成して返却
            return Response.ok(stream).header("Content-Disposition", "attachment; filename=hello.csv").build();
        }
    
        /**
         * CSV ファイルを直接 StreamingOutput に書き出してファイルをダウンロード
         *
         * @return
         */
        @GET
        @Path("csv")
        @Produces("text/plain")
        public Response filedownload() {
            StreamingOutput stream = (OutputStream out) -> {
                try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))) {
    
                    writer.write("LineNumber");
                    writer.newLine();
                    int lineNumber = 10000;
                    while (lineNumber > 0) {
                        String lineData = String.format("%06d", lineNumber);
                        writer.write(lineData);
                        writer.newLine();
    
                        lineNumber--;
    
                    }
                    writer.flush();
                }
            };
    
            // レスポンスを返す
            return Response.ok(stream).header("Content-Disposition", "attachment; filename=hello.csv").build();
        }
    
    }
    
[/code]


CC BY-SA 3.0
2018-02-20T13:00:09.140
41871
2018-02-20T13:00:09.140
27410
40201
answer