java - servlet/rest Controller 下载 log4j 日志文件内容没有完全结束

标签 java file servlets filereader spring-restcontroller

在 Spring Web 应用程序中(尽管我不认为这与 Spring 相关),我创建了一个 REST GET 资源,允许下载当前的 log4j2 文件内容,但请求(来自浏览器和 cUrl)不会终止于部署在远程生产服务器上的 Web 应用程序,而它们通常终止于我的 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 header :在 Linux (Ubuntu) 服务器上,只有在文件长度中减去 3 才有效:

response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(tempCopy.toFile().length() - 3));

我尝试在下载前将原始文件复制到临时文件,但似乎没有帮助。

当然,如果我不发送任何 Content-Length header ,一切都很好。

最佳答案

我解决了在 Content-Type header 中指定字符集的问题:

response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain; charset=utf-8");

没有它,Linux 服务器就会返回:

Content-Type: text/plain;charset=ISO-8859-1

关于java - servlet/rest Controller 下载 log4j 日志文件内容没有完全结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52521300/

相关文章:

java - 如何在用户按 Tab 时检查文本框值

java - 为什么使用 Android 插件的 Jenkins 多配置作业失败?

java - 检测浏览器在 http 请求响应周期中关闭

java - AEM:更改了 servlet 的 url

python - 在python中删除文件的一部分

javascript - 填充 chartjs ajax servlet

java - JAR 中不会显示启动画面

java - 您可以使用 Retrofit 2 和 Gson 将 ISO 8601 时间戳直接映射到 OffsetDateTime 或 ZonedDateTime 吗?

java - 解析任务列表

c# - WPF/C# : Where should I be saving user preferences files?