簡體   English   中英

如何使用 Jersey 從服務器發送大文件?

[英]How to send a large file from server using Jersey?

我正在嘗試下載並保存一個大型 zip 文件。 The zip file is possibly larger than the heap, so I want to use a stream to avoid java.lang.OutOfMemoryError: Java heap space error.

另外,zip 大文件是根據要求生成的,所以我想在下載后刪除該文件。

我目前的代碼是

@POST
@Path("/downloadLargeZip")
public Response largeZip() throws FileNotFoundException {
    File file = generateZipFile(); // generates zip file successfully
    FileInputStream input = new FileInputStream(file);
    StreamingOutput so = os -> {
        try {
            int n;
            byte[] buffer = new byte[1024];
            while ((n = input.read(buffer)) >= 0) {
                os.write(buffer, 0, n);
            }
            os.flush();
            os.close();
        } catch (Exception e) {
            throw new WebApplicationException(e);
        }
    };
    return Response.ok(so).build();
}

我當前的客戶端代碼是

import { saveAs } from 'browser-filesaver/FileSaver.js';

save() {
    this.http.post<any>('url', '', { observe: 'response', responseType: 'blob'})
      .subscribe(res => {
        this.downloadFile(res);
    });
}

downloadFile(response: any) {
    const contentDisposition = 'attachment; filename="KNOWN_FILE_NAME"'; // response.headers('content-disposition'); - response object has no headers
    // Retrieve file name from content-disposition
    let fileName = contentDisposition.substr(contentDisposition.indexOf('filename=') + 9);
    fileName = fileName.replace(/\"/g, '');
    const contentType = 'application/zip'; // response.headers('content-type');
    const blob = new Blob([response.data], { type: contentType });
    saveAs(blob, fileName);
}

我的代碼有一些問題:

  1. 使用開發工具檢查響應,它沒有標題( normalizedNames是沒有條目的 map )或數據。
  2. 檢查保存的 zip 文件,我無法使用 WinRAR 打開它。 錯誤是The archive is either in unknown format or damaged
  3. 嘗試用 Notepad++ 打開 zip 文件,內容是文本undefined

響應的 JSON 表示是

{
    "headers":{
        "normalizedNames":{  
        },
       "lazyUpdate":null
    },
    "status":200,
    "statusText":"OK",
    "url":"URL",
    "ok":true,
    "type":4,
    "body":{ 
    }
}

盡管body確實包含數據{size: 2501157, type: "application/json"} 請忽略這個數字(我猜它是 zip 文件大小,以字節為單位,實際文件會大得多)。

我究竟做錯了什么? 如何讀取 stream 並保存生成的 zip 文件? 我認為問題出在我的downloadFile function 中,但我不知道要在那里更改什么。

任何幫助,將不勝感激。

我需要徹底改變我處理問題的方式。

服務器現在將生成文件並為客戶端返回一個 URI。 然后客戶端將通過給定的 URI 下載文件。

服務器代碼

@POST
@Path("/create")
public Response createLogs(String data) {
    String fileName = generateFileAndReturnName(data);
    if (fileName != null) {
        return Response.created(URI.create(manipulateUri(fileName))).build();
    }
    return Response.status(500).build();
}

客戶端代碼

save() {
  this.http.post<any>(this.baseUrl + '/create', this.data, { observe: 'response'}).subscribe(postResponse => {
    if (postResponse.status !== 201) {
      this.logger.error('Failed.');
      return;
    }
    postResponse.headers.keys(); // lazy init headers
    const uri = postResponse.headers.get('location');
    if (!uri) {
      this.logger.error('URI not present.');
      return;
    }
    const link = document.createElement('a');
    link.href = uri;
    link.setAttribute('download', 'fileName.fileExtension');
    document.body.appendChild(link);
    link.click();
    if (link.parentNode) {
      link.parentNode.removeChild(link);
    }
  });
}

現在可以正常使用 40GB 文件(32GB RAM,因此文件肯定比任何分配的堆都大)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM