POI导出时写一份到ftp服务器,一份下载给客户端
导语:
昨天接到项目经理这么一个需求,让我在POI导出Excel的时候写一份到我之前搭建的ftp服务器上。所以就有了这篇博客首先我们来分析下之前的业务逻辑:我们创建并构造了一个workbook,然后构建了一个OutputStream输出流,然后我们把数据写入输出流中就可以被客户端下载。
现在我们要在此基础上写一份到ftp服务器
那么我们就需要两个流,首先一个输入流把文件写到ftp服务器,然后需要一个输出流把文件输出到客户端。千万不要用workbook.write(out)一份到客户端,然后又workbook.write(in)一份到ftp,会报错的。Stream is closed,(为啥报错,我也解释不清希望大神解惑一下)
正确思路应该是先写一份到ftp服务器,然后再读取这个文件,然后再把这个文件输出给客户端
参考:
来看代码吧:
1. 我们只需要对 oi实现百万级数据导出 中的 CommentController 稍作修改,然后配合一些工具类就可以实现
/**
* excel导出功能
* @param commentSearch
* @param response
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/exportCommentInfo")
@ResponseBody
@NoRepeatRequest
public BaseDTO exportCommentInfo(CommentSearch commentSearch, HttpServletResponse response, HttpServletRequest request) throws Exception{
LOGGER.info("CommentController.exportCommentInfo start");
long startTime = System.currentTimeMillis();
LOGGER.info("开始下载.........................................");
List<ErrorInfo> errors = null;
int result = ;
String fileName = FileNameUtils.getExportCommontExcelFileName();
OutputStream fileOut = null;
SXSSFWorkbook workbook = null;
try {
LOGGER.debug("classpath: " + fileName);
workbook = new SXSSFWorkbook();
commentService.exportCommentInfo(request,workbook, commentSearch);
// 定义excel文件名
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\""
+ URLEncoder.encode(fileName, "UTF-8") + "\"");
// 定义输出流
fileOut = response.getOutputStream();
// 调用导出方法
//workbook.write(fileOut);
//写一份到ftp服务器
ByteArrayOutputStream os = new ByteArrayOutputStream();
workbook.write(os);
byte[] b = os.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(b);
FtpUtil.uploadFileToFtp(fileName,in,fileOut);
workbook.dispose();
} catch (Exception e) {
LOGGER.error("InterfaceInfoController.exportInterfaceInfo Exception: ", e);
ErrorInfo errorInfo = new ErrorInfo("system.error", "系统异常!");
errors = Arrays.asList(errorInfo);
request.getSession().setAttribute("exportStatus","error");
}finally {
fileOut.close();
workbook.close();
}
LOGGER.info("下载完成....|||||.......用时:" + (System.currentTimeMillis() - startTime));
return tranferBaseDTO(errors, result);
}
1.首先把workbook写到 ByteArrayOutputStream 输出流中,然后转换成 字节数组 byte[] b 在转换成 ByteArrayInputStream 输入流用来写入ftp
ByteArrayOutputStream os = new ByteArrayOutputStream();
workbook.write(os);
byte[] b = os.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(b);
FtpUtil.uploadFileToFtp(fileName,in,fileOut);
2.然后转换成 字节数组 在转换成输入流用来写入ftp ,主要看这几个方法
/**
* 上传重载 二进制流
* @param filename
* @param input
* @return
*/
public static boolean uploadFileToFtp(String filename, ByteArrayInputStream input, OutputStream fileOut) {
getPropertity();
return uploadFileToFtp( host, port, username, password, basePath,
filePath, filename, input, fileOut);
} /**
* Description: 向FTP服务器上传文件 二进制流文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @return 成功返回true,否则返回false
*/
public static boolean uploadFileToFtp(String host, String port, String username, String password, String basePath,
String filePath, String filename, ByteArrayInputStream input, OutputStream fileOut) {
FTPClient ftp = new FTPClient();
try {
//开启ftp连接
boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
if(!result){
return result;
}
if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
LOCAL_CHARSET = "UTF-8";
}
}
//防止中文乱码
filename = new String(filename.getBytes(LOCAL_CHARSET),SERVER_CHARSET );
//为了加大上传文件速度,将InputStream转成BufferInputStream , InputStream input
BufferedInputStream in = new BufferedInputStream(input);
//加大缓存区
ftp.setBufferSize(1024*1024);
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
if (!ftp.storeFile(filename, in)) {
return false;
}
//写一份给客户端
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(filename)) {
ftp.retrieveFile(ff.getName(), fileOut);
fileOut.close();
}
}
in.close();
ftp.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return true;
} /**
* 连接ftp服务器并切换到目的目录
* 调用此方法需手动关闭ftp连接
* @param ftp
* @param host
* @param port
* @param username
* @param password
* @param basePath
* @param filePath
* @return
*/
private static boolean connectFtp( FTPClient ftp,String host, String port, String username, String password, String basePath, String filePath){
boolean result = false;
try {
int portNum = Integer.parseInt(port);
int reply;
// 连接FTP服务器
ftp.connect(host, portNum);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(username, password);
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath+filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) {
continue;
}
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
result = true;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
主要是 我们为了加快文件上传速度把刚才传入的 ByteArrayInputStream 转换成了 BufferedInputStream
BufferedInputStream in = new BufferedInputStream(input);
然后我们把 BufferedInputStream 写入到ftp服务器
ftp.storeFile(filename, in)
到这里第一步就完成了,接下来是从服务器下载我们刚才上传 文件,然后通过刚才传入的 输出流 fileOut 输出到客户端
//写一份给客户端
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(filename)) {
ftp.retrieveFile(ff.getName(), fileOut);
fileOut.close();
}
}
POI导出时写一份到ftp服务器,一份下载给客户端的更多相关文章
- 使用批处理文件在FTP服务器 上传下载文件
1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt 192.168.1.1 建立一个 ...
- Spring学习---Spring中利用组件实现从FTP服务器上传/下载文件
FtpUtil.java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcepti ...
- ftp服务器上传下载共享文件
1 windows下搭建ftp服务器 https://blog.csdn.net/qq_34610293/article/details/79210539 搭建好之后浏览器输入 ftp://ip就可以 ...
- POI导出时,将指定的列设置为下拉列表
本示例设置第2列为下拉框(下拉框内容为:是/否),从第5行开始到5657行结束. 关键代码示例: ComboxList = new String[]{"是","否&quo ...
- WordPress更新时提示无法连接到FTP服务器的解决方案
这几天在搭建主站的时候,更新wordpress时无法连接到FTP原因服务器 解决方法如下: 在WordPress目录下找到wp-config.php文件并编辑,在最后一行加上: define('FS_ ...
- 从ftp服务器进行批量下载,处理文件名保存时重名的问题,更改重名文件名方式为给后面加1、2、3等数字,保持后缀不变
公司最近有一个从ftp批量下载文件的需求,但是文件名重复总会报错 没办法,自己下班后写了一个小算法 仿照桶排序的原理,实现了这个小功能,直接上代码: String[] test = {"ha ...
- Node.js使用ftp连接远程ftp服务器枚举和下载文件示例
示例代码: var Ftp = require('ftp'); var fs = require('fs'); var path = require('path'); // 首先判断参数中是否包含{d ...
- FTP服务器的搭建与配置
主要来源:http://www.cnblogs.com/helonghl/articles/5533857.html 1.安装FTP服务器: yum install vsftpd -y 2.启动FTP ...
- Ubantu下FTP服务器资源进行控制
在FTP服务器的管理中无论对本地用户还是匿名用户,对于FTP服务器资源的使用都需要进行控控制, 避免由于负担过大造成FTP服务器运行异常, 可以添加以下配置项对FTP客户机使用FTP服务器资源进行控制 ...
随机推荐
- Spring Boot 2 (七):Spring Boot 如何解决项目启动时初始化资源
Spring Boot 2 (七):Spring Boot 如何解决项目启动时初始化资源 在项目启动的时候需要做一些初始化的操作,比如初始化线程池,提前加载好加密证书等.今天就给大家介绍一个 Spri ...
- java bean属性拷贝工具类比对(性能+功能)
业务系统中经常需要两个对象进行属性的拷贝,不能否认逐个的对象拷贝是最快速最安全的做法,但是当数据对象的属性字段数量超过程序员的容忍的程度比如通常超过5个属性的时候,代码因此变得臃肿不堪,使用一些方便的 ...
- 观实验室PPT演讲有感
outline 一定要有 说话的语速要慢,压制住紧张的心情 提前一天发布PPT dont` argue with audience, especially professor and teachers ...
- 使用UI管理docker
比较全面的对比 wangzi19870227 比较推荐的有两种(http://dockone.io/article/225): Shipyard 和 dockerui https://docs.doc ...
- python --- 10 *args **kwargs 命名空间 作用域 函数的嵌套
函数进阶 1. "*" 和 "**" ① 在形参位置时 都是聚合的作用 *args 位置参数→元组 **kwargs 关键字参数→字典 混 ...
- git如何修改用户名和邮箱名?
答: 使用git config --global --edit即可进行修改
- 关于link标签的用法, 不声明rel=stylesheet则无效? 在ff中必须声明rel属性!
void 无效的, 空的; invalid: 无效的, void 和 invalid 在表示无效的时候, 是一样的, 等同的 the treaty (条约) was declared invalid ...
- 数论+矩阵快速幂|斐波那契|2014年蓝桥杯A组9-fishers
标题:斐波那契 斐波那契数列大家都非常熟悉.它的定义是: f(x) = 1 .... (x=1,2) f(x) = f(x-1) + f(x-2) .... (x>2) 对于给定的整数 n 和 ...
- 找质数|计蒜客2019蓝桥杯省赛 B 组模拟赛(一)
找质数 思路:数据大,用线性筛,筛选素数表,最后查表:题目让我们查找相加等于n的两个数,那么我们就枚举1个素数a,在素数表中查找是否存在n-a也是素数. 注意事项:数据大,不宜用输入输出流,cout. ...
- CodeChef - ELHIDARR Find an element in hidden array(互动题)题解
题意:有一串不递减的串,串中的任意元素都有k个,除了一个元素,他只有1 <= n < k-1个,你现在能向oj做出以下操作: 输出:1 pos,oj会返回pos位置的元素值 输出:2 va ...