Angular2 скачать ZIP используя POST с переопределением GET - PullRequest
0 голосов
/ 01 октября 2018

Я отправляю данные в формате JSON на сервер с клиента Angular2 и ожидаю возврата ZIP-файла.

Я написал метод JAX-RS для генерации ZIP-файла и помещения его в/ tmp каталог для скачивания.У меня нет проблем с получением JSON downloadInfo от клиента или сгенерированием ZIP-файла, поэтому я пропустил их в этом примере.Все, что делает этот пример, это отправляет ответ, который является предварительно созданным ZIP-файлом.

@Consumes({MediaType.APPLICATION_JSON})
@POST
@Path("test-download")
@Produces("application/octet-stream")
public Response getZip(String downloadInfo,
                       @Context SecurityContext securityContext)
{
  System.out.println("downloadInfo=" + downloadInfo);
  File zipFile = new File("/tmp/file.zip");
  return Response.ok(zipFile)
      .header("Content-Disposition", "attachment; filename=" + zipFile.getName())
      .build();
}

Я использую POST с переопределением GET, потому что мне нужно отправить большой объем данных в запросе и некоторые изДанные запроса содержат символы, которые не могут быть закодированы в URL.Данные запроса здесь не отображаются.Вот соответствующий код Angular2:

downloadZip(): void {
    let downloadZipUrl = 'http://myserver/test-download';
    let json: any = {};
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('responseType', ResponseContentType.Blob);
    headers.append('X-HTTP-Method-Override', 'GET');

    this.http.post(downloadZipUrl, json, {headers: headers}).subscribe(response => {
      var blob = new Blob([response['_body']], {type: 'application/zip'});
      var url= URL.createObjectURL(blob);
      window.open(url);
    });
}

Когда я запускаю это, я загружаю ZIP-файл, но ZIP-файл кажется поврежденным.Если я «катлю» загруженный файл на экран, я вижу кучу символов замены Юникода (знак вопроса внутри ромба).Если я «кошачий» оригинальный ZIP, я не вижу этих символов.Кроме того, размер загружаемого файла больше, чем исходный файл.

Я провел немало исследований по этому вопросу и попробовал различные варианты типов носителей (application / octet-stream, application / zip)и в клиенте Angular2, и на сервере JAX-RS, и в кодировке клиента, все безрезультатно.

Обновление 10/4/2018

Если я нажмуURL с браузером (без клиента Angular2) ZIP загружается правильно.Это указывает на проблему со стороной Angular2.

1 Ответ

0 голосов
/ 05 октября 2018

Решение

Я получил это работает.Вот мое решение.Внутренний метод JAX-RS:

@Consumes({MediaType.APPLICATION_JSON})
@POST
@Path("test-download")
@Produces("application/zip")
public Response getZip(String downloadInfo,
                       @Context SecurityContext securityContext)
{
  System.out.println("downloadInfo=" + downloadInfo);
  File zipFile = new File("/tmp/file.zip");
  return Response.ok(zipFile)
      .header("Content-Disposition", "attachment; filename=" + zipFile.getName())
      .build();
}

Что изменилось в методе JAX-RS от вопроса к решению?Не важно.Я изменил «application / octet-stream» на «application / zip», но я протестировал обе и обе работы.

Код Angular2:

downloadZip(): void {
    let downloadZipUrl = 'http://myserver/test-download';
    let json: any = {};

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append('X-HTTP-Method-Override', 'GET');

    let options = new RequestOptions({responseType: ResponseContentType.Blob});
    options.headers = headers;

    this.http.post(downloadZipUrl, json, options).subscribe(response => {
        // Get the file name from the content disposition.
        let contentDisposition = response.headers.get('Content-Disposition');
        let fileName = contentDisposition.split(';')[1].trim().split('=')[1];
        fileName = fileName.replace(/"/g, '');   // Get rid of double quotes.

        // Get and automatically download the file.
        let blob = new Blob([response._body], {type: 'application/zip'});
        let downloadLink = document.createElement('a');
        let url = URL.createObjectURL(blob);
        downloadLink.setAttribute('href', url);
        downloadLink.setAttribute('download', fileName);
        downloadLink.style.visibility = 'hidden';
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
    });
}

В чем разница?Использование RequestOptions:

let options = new RequestOptions({responseType: ResponseContentType.Blob});

В какой-то момент я попытался вставить:

{responseType: ResponseContentType.Blob}

в сам вызов http.post, но у меня это не сработало.Может быть, я сделал это неправильно.

...