Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java servlet/rest控制器下载log4j日志文件内容不';完好无损_Java_File_Servlets_Filereader_Spring Restcontroller - Fatal编程技术网

Java servlet/rest控制器下载log4j日志文件内容不';完好无损

Java servlet/rest控制器下载log4j日志文件内容不';完好无损,java,file,servlets,filereader,spring-restcontroller,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

在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();

                    // ...
我认为问题在于
内容长度
头:在Linux(Ubuntu)服务器上,只有将
3
减去文件长度,它才有效:

response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(tempCopy.toFile().length() - 3));
在下载之前,我尝试将原始文件复制到临时文件,但似乎没有任何帮助


当然,如果我不发送任何
内容长度
标题,一切都很好。

看起来像cURL相关问题,这是因为
内容配置
标题的
文件名
部分(这里的问题是关于日志文件名格式的,主要是日期部分)

和最初描述了
内容配置
的形成方式;所以设置
filename
部件的正确方法是对其进行编码:

String fileName = URLEncoder.encode(f.getName(), "UTF-8");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");

补充资料 顺便说一句,后来引入了在可选的“扩展”参数中使用编码的可能性(在我们的例子中,
filename*
);它受到现代浏览器的支持

它使您可以添加可选的“扩展”参数:

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

这里,支持RFC 5987的用户代理将使用
filename*
参数,而旧的用户代理将忽略该参数,并将使用
filename

我已解决在
内容类型
标题中指定字符集的问题:

response.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain; charset=utf-8");
如果没有它,Linux服务器将返回:

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

我在浏览器上也得到了同样的结果,尽管我没有提到(要编辑);我试过你的解决方案,它仍然不起作用,加上现在cUrl说还有
5个字节要读
。错过了它,这也是事实的一部分,在大多数情况下,它是编码相关的东西(标题、正文),让我投票支持你。