Как вызвать конечную точку REST в цикле с помощью RestTemplate и вернуть zip всех ответов потока
ПЕРЕОПРЕДЕЛЕНИЕ ПРОБЛЕМЫ
Надеюсь, кто-то может дать некоторые рекомендации.
То, что я пытаюсь сделать, это как показано ниже
У меня есть контроллер Rest для вызова GET.
У меня есть список задач Qlik, для которых я вызываю метод GET для RestTemplate в цикле для каждой задачи. Каждый вызов возвращает поток, который я сохраняю в виде файла.
Вне цикла с вызовами RestTemplate для каждой задачи я хочу добавить эти файлы в zip-файл, а затем вернуть этот zip-файл из конечной точки исходного вызова.
@GetMapping("/export-task-all-SO/{qlikenv}")
public ResponseEntity<?> exportTaskAllSO(HttpServletResponse response, @PathVariable String qlikenv) {
qlikEnv = qlikenv;
try {
getTaskList(qlikEnv);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
// list of file paths for download
List<String> filepaths = createFilesSO(tasksList);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=example.zip");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
int BUFFER_SIZE = 1024;
StreamingResponseBody streamResponseBody = out -> {
final ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());
ZipEntry zipEntry = null;
InputStream inputStream = null;
try {
for (String path : filepaths) {
File file = new File(path);
zipEntry = new ZipEntry(file.getName());
inputStream = new FileInputStream(file);
zipOutputStream.putNextEntry(zipEntry);
byte[] bytes = new byte[BUFFER_SIZE];
int length;
while ((length = inputStream.read(bytes)) >= 0) {
zipOutputStream.write(bytes, 0, length);
}
}
// set zip size in response
response.setContentLength((int) (zipEntry != null ? zipEntry.getSize() : 0));
} catch (IOException e) {
logger.error("Exception while reading and streaming data {} ", e);
} finally {
if (inputStream != null) {
inputStream.close();
}
if (zipOutputStream != null) {
zipOutputStream.close();
}
}
};
return ResponseEntity.ok(streamResponseBody);
}
private List<String> createFilesSO(List<String> tasksList) {
boolean setAccept = true;
HttpEntity<String> requestEntity = setAPISessionIdHeader(setAccept);
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());
List<String> filepaths = new ArrayList<>();
for (String taskName : tasksList) {
try {
ResponseEntity<byte[]> responseEntity = restTemplate.exchange(getAPIFormattedUrl("export-task", qlikEntManagerServers.get(0), taskName), HttpMethod.GET, requestEntity, byte[].class, "1");
FileOutputStream output = null;
if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
File file = new File(taskName + ".json");
output = new FileOutputStream(file);
IOUtils.write(responseEntity.getBody(), output);
filepaths.add(file.getPath());
}
} catch (RuntimeException | IOException nfe) {
nfe.printStackTrace();
System.out.println("taskname " + taskName + " position of taskName " + tasksList.indexOf(taskName) + " exception " + nfe.getClass().getName());
}
}
return filepaths;
}
Когда я вызываю эту конечную точкуhttp://localhost:11111/qlik-rest-client/export-task-all-SO/dev
- Я получаю 2-байтовый файл example.zip - из-за настройки ответа.
Я думаю, что делаю это неправильно, возвращаясь из вызова REST после создания отдельных файлов. Может ли кто-нибудь пролить свет на то, как я могу это исправить?
Исходное определение проблемы
Я работаю над задачей, в которой мне нужно заархивировать файлы из потоков, возвращаемых вызовом REST.
Я работаю над вызовами Qlik REST, где сначала я получаю список задач, определенных в URL-адресе сервера , а затем перебираю этот список, чтобы получить TaskDetails для каждой из задач через вызов REST для каждого URL- адреса задачи . Второй вызов REST возвращает поток. Мне удалось прочитать вывод каждой детали задачи и сохранить возвращенное содержимое потока в виде файла json. но после этого, когда я пытаюсь заархивировать файлы, чтобы отправить их обратно как StreamingResponseBody, это не работает. После сохранения файлов с указанием пути я попытался использовать zip-часть, аналогичную тому, как это делается здесь и здесь . Но выполнение даже не входит в функциональный код
В приведенном ниже фрагменте (взятом из ссылок, которые я разместил здесь) он не печатает внутреннюю часть StreamingResponseBody streamResponseBody = out -> {
System.out.println("before StreamingResponseBody streamResponseBody = out -> { ");
StreamingResponseBody streamResponseBody = out -> {
System.out.println("inside StreamingResponseBody streamResponseBody = out -> { ");
Что я делаю не так или что-то упускаю? Возможно ли сделать то, что я пытаюсь сделать?
Спасибо