Вот задача - необходимо создать файл на основе некоторых данных со стороны интерфейса (JavaScript). Схема довольно проста:Как избежать липких сессий при загрузке файла?
UI делает запрос HTTP асинхронной POST на сервер и предоставляет некоторые JSON данные:
$.ajax({ url: '/reports', type: "POST", data: JSON.stringify({...}), success: function (uuid) { window.location = "/reports/" + uuid; } });
сервер получает запрос, создает файл, помещает его в файловой системе и возвращает уникальный идентификатор:
@RequestMapping(value = "/reports", method = RequestMethod.POST) public String generateReport(ReqData data) throws IOException { final String fileUuid = UUID.randomUUID(); ... //generate a report and return filename ... return fileUuid; }
стороны UI получает уникальный идентификатор файла, созданного и просит его:
success: function (uuid) { window.location = "/reports/" + uuid; }
Сервер выводит запрашиваемый файл:
@RequestMapping(value = "/reports/{uuid}", method = RequestMethod.GET) public ResponseEntity<InputStreamResource> downloadReport(@PathVariable("uuid") String fileUuid) throws IOException { final String resultFileName = fileUuid + ".txt"; final Path resultFile = Paths.get(resultFileName); return ResponseEntity .ok() .header("Content-Disposition", "attachment; filename=\"" + resultFileName + "\"") .contentLength(Files.size(resultFile)) .contentType(MediaType.parseMediaType("text/plain")) .body(new InputStreamResource(Files.newInputStream(resultFile))); }
Проблема начинается тогда, когда мы рассматриваем эту схему с несколькими серверами. Если у нас есть два экземпляра Server_A и Server_B и балансировщик нагрузки перед ними, тогда нам нужно убедиться, что оба упомянутых выше запроса перейдут на один и тот же сервер. При этом требуются липкие сеансы. Предоставление абсолютного пути с сервером, указанным как http://server_a/reports/123, не является хорошим вариантом, поскольку мы хотим сделать все серверы недоступными из внешнего мира.
Итак, какие варианты доступны для реализации загрузки файлов, а также предотвращения липких сеансов?
Подход 4: невозможно вызвать диалог сохранения в браузере с помощью ajax - http://stackoverflow.com/questions/12098178/prompt-user-to-save-file-through-ajax-call, поэтому есть два вызова ajax –