我再后台进行rest请求excel文件资源下载时,出现了

我们项目用的微服务,我负责界面展示,在后台使用rest请求api来获取文件资源,在进行文件请求时,API调用各个服务在FTP上生成excel文件,然后API再从ftp上下载文件并且通过流的方式返回给我。

第一步排除FTP上文件生成是不是有问题

          直接FTP把文件下载到本地,打开文件是没有问题的。那么就可以定位到时项目进行文件传输的时候出现问题。

第二步排查是不是在下载时没有设置response.addHeader("Content-Length", String.valueOf(fis.getChannel().size()));

 api的文件下载代码

if(result.getFileName().split("\\.")[1].contains("xls")){
	if("xlsx".equals(result.getFileName().split("\\.")[1])){
		response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
	}else{
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
	}
response.setHeader("Content-Disposition", "attachment;filename=\"" + java.net.URLEncoder.encode(result.getFileName(), "UTF-8") + "\"");
response.addHeader("msg", Constants.SUCCESS_MSG);
			        //打开输出流
OutputStream os = response.getOutputStream();
FileInputStream fis = new FileInputStream(new File(result.getReportAddress()));
response.addHeader("Content-Length", String.valueOf(fis.getChannel().size()));
// 读取文件并输出
byte[] b = new byte[8192];
int i = 0;
while ((i = fis.read(b)) > 0) {
	os.write(b, 0, i);
}
// 关闭流
fis.close();
os.flush();
os.close();

添加完response的内容长度之后, 在windows环境通过tomcat启动进行文件下载是没有问题的,但是在linux环境下启动项目下载依旧还是原来的问题,然后我们就把项目转换到了环境编码上

查看linux环境编码,是utf8,所以应该不是环境编码的问题

我们又把矛头抛向了ftp的下载上

第三步ftp文件下载代码

   FTPClient ftp = new FTPClient();
   logger.info("FTP ip:{},端口:{},用户名:{},文件目录:{},自定义文件目录:{},文件名:{},本地文件路径:{}",host, port, username, remotePath, customPath,
	             fileName, localPath);
	try {
	    int reply;
	    ftp.setControlEncoding("utf-8");
	    ftp.connect(host, port);
	    // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
	    ftp.login(username, password);// 登录
	    reply = ftp.getReplyCode();
	    if (!FTPReply.isPositiveCompletion(reply)) {
	        ftp.disconnect();
	        return result;
	     }
	     ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
	     logger.info("转移到FTP服务器目录:"+remotePath);
	     ftp.changeWorkingDirectory(customPath);// 转移到FTP服务器目录
	     logger.info("转移到FTP指定目录:"+customPath);
         File path = new File(localPath);
         if (path.exists()) {
             if (path.isDirectory()) {
                System.out.println("dir exists");
              } else {
                System.out.println("the same name file exists, can not create dir");
              }
          } else {
               System.out.println("dir not exists, create it ...");
                path.mkdir();
          }  
          File localFile = new File(localPath + "/" + fileName);
          OutputStream is = new FileOutputStream(localFile);
          ftp.retrieveFile(fileName, is);
         is.close();
         ftp.logout();

然后看下是不是FTP进行下载时编码的问题

https://www.cnblogs.com/shunxiyuan/p/5413420.html

这篇文章中提到了一些疑惑

 

然后在ftp下载中添加了 

ftp.enterLocalPassiveMode(); //设置被动模式
ftp.setFileType(ftpc.BINARY_FILE_TYPE); //设置下载文件为二进制模式
ftp.setFileTransferMode(ftpc.STREAM_TRANSFER_MODE); ///传输文件为流的形式

这三句话完美解决。

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐