В веб-приложении Spring (хотя я не думаю, что это связано с Spring) я создал ресурс REST GET, который позволяет загружать текущее содержимое файла log4j2, но запросы (как из браузеров, так и из cUrl) этого не делаютзавершить работу с веб-приложением, развернутым на удаленном производственном сервере - в то время как они обычно заканчиваются на моей машине для разработки Windows.
Более того, cUrl говорит, что еще есть байты для получения:
* transfer closed with 3 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with 3 bytes remaining to read
Этосоответствующий код:
// ...
import org.springframework.http.HttpHeaders;
// ...
@RestController
@RequestMapping(path="/logs", produces="application/json")
public class LogController {
// ...
@GetMapping(path="/{appenderName}/contents", produces="text/plain")
public void download(@PathVariable String appenderName, HttpServletResponse response) {
// ...
org.apache.logging.log4j.Logger rootLogger = LogManager.getRootLogger();
if(rootLogger instanceof Logger) {
Logger l = (Logger) rootLogger;
if(l.getAppenders().containsKey(appenderName)) {
Appender appender = l.getAppenders().get(appenderName);
if(appender instanceof FileAppender) {
((FileAppender) appender).getManager().flush();
final File f = new File(((FileAppender) appender).getFileName());
response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + f.getName() + "\"");
Path tempCopy = Files.createTempFile("log-", null);
Files.copy(f.toPath(), tempCopy, StandardCopyOption.REPLACE_EXISTING);
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(tempCopy.toFile().length()));
Reader reader = new FileReader(tempCopy.toFile());
IOUtils.copy(reader, response.getWriter());
reader.close();
tempCopy.toFile().delete();
// ...
Я думаю, что проблема связана с заголовком Content-length
: на сервере Linux (Ubuntu) он работает, только если вычесть 3
из длины файла:
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(tempCopy.toFile().length() - 3));
Я пытался скопировать исходный файл во временный файл перед загрузкой, но, похоже, это не помогло.
Конечно, все нормально, если я не отправляю заголовок Content-Length
.