导语:

  昨天接到项目经理这么一个需求,让我在POI导出Excel的时候写一份到我之前搭建的ftp服务器上。所以就有了这篇博客首先我们来分析下之前的业务逻辑:我们创建并构造了一个workbook,然后构建了一个OutputStream输出流,然后我们把数据写入输出流中就可以被客户端下载。

  现在我们要在此基础上写一份到ftp服务器

  那么我们就需要两个流,首先一个输入流把文件写到ftp服务器,然后需要一个输出流把文件输出到客户端。千万不要用workbook.write(out)一份到客户端,然后又workbook.write(in)一份到ftp,会报错的。Stream is closed,(为啥报错,我也解释不清希望大神解惑一下)

  正确思路应该是先写一份到ftp服务器,然后再读取这个文件,然后再把这个文件输出给客户端

参考:

ftp服务器搭建(离线安装vsftpd),配置

poi实现百万级数据导出

来看代码吧:

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服务器,一份下载给客户端的更多相关文章

  1. 使用批处理文件在FTP服务器 上传下载文件

    1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt   192.168.1.1 建立一个 ...

  2. Spring学习---Spring中利用组件实现从FTP服务器上传/下载文件

    FtpUtil.java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExcepti ...

  3. ftp服务器上传下载共享文件

    1 windows下搭建ftp服务器 https://blog.csdn.net/qq_34610293/article/details/79210539 搭建好之后浏览器输入 ftp://ip就可以 ...

  4. POI导出时,将指定的列设置为下拉列表

    本示例设置第2列为下拉框(下拉框内容为:是/否),从第5行开始到5657行结束. 关键代码示例: ComboxList = new String[]{"是","否&quo ...

  5. WordPress更新时提示无法连接到FTP服务器的解决方案

    这几天在搭建主站的时候,更新wordpress时无法连接到FTP原因服务器 解决方法如下: 在WordPress目录下找到wp-config.php文件并编辑,在最后一行加上: define('FS_ ...

  6. 从ftp服务器进行批量下载,处理文件名保存时重名的问题,更改重名文件名方式为给后面加1、2、3等数字,保持后缀不变

    公司最近有一个从ftp批量下载文件的需求,但是文件名重复总会报错 没办法,自己下班后写了一个小算法 仿照桶排序的原理,实现了这个小功能,直接上代码: String[] test = {"ha ...

  7. Node.js使用ftp连接远程ftp服务器枚举和下载文件示例

    示例代码: var Ftp = require('ftp'); var fs = require('fs'); var path = require('path'); // 首先判断参数中是否包含{d ...

  8. FTP服务器的搭建与配置

    主要来源:http://www.cnblogs.com/helonghl/articles/5533857.html 1.安装FTP服务器: yum install vsftpd -y 2.启动FTP ...

  9. Ubantu下FTP服务器资源进行控制

    在FTP服务器的管理中无论对本地用户还是匿名用户,对于FTP服务器资源的使用都需要进行控控制, 避免由于负担过大造成FTP服务器运行异常, 可以添加以下配置项对FTP客户机使用FTP服务器资源进行控制 ...

随机推荐

  1. 【题解】Luogu P2604 [ZJOI2010]网络扩容

    原题传送门:P2604 [ZJOI2010]网络扩容 这题可以说是板题 给你一个图,先让你求最大流 再告诉你,每条边可以花费一些代价,使得流量加一 问至少花费多少代价才能使最大流达到k 解法十分简单 ...

  2. What is probabilistic programming? | 中文翻译

    What is probabilistic programming? | 中文翻译 Probabilistic languages can free developers from the compl ...

  3. yum all installed dependent packages while removing a package in centos 7?

    how to remove all installed dependent packages while removing a package in centos 7? # yum history # ...

  4. 16 级高代 II 思考题九的七种解法

    16 级高代 II 思考题九  设 $V$ 是数域 $\mathbb{K}$ 上的 $n$ 维线性空间, $\varphi$ 是 $V$ 上的线性变换, $f(\lambda),m(\lambda)$ ...

  5. Chrome视频解析插件

    我们在观看一些平台的视频资源时,比如优酷视频.腾讯视频.爱奇艺等等,通常都会需要VIP资格才能观看到更稀缺的视频,如何通过破解来实现免VIP观看呢?下面我们来看一看怎么用Chrome插件实现. 视频解 ...

  6. 【做题】Codeforces Round #429 (Div. 2) E. On the Bench——组合问题+dp

    题目大意是给你n个数,求相邻两数相乘不是完全平方数的排列数. 一开始看到这题的时候,本人便想给相乘为完全平方数的数对建边,然后就写萎了... 后来通过集体智慧发现这个重要性质:对于自然数a,b,c,若 ...

  7. Hyper

    https://github.com/zeit/hyper https://gist.github.com/coco-napky/404220405435b3d0373e37ec43e54a23 Ho ...

  8. centos7重新调整分区大小

    As others have pointed out, XFS filesystem cannot be shrunk. So your best bet is to backup /home, re ...

  9. python 之 知识点(1)

    在python是使用bif=built in functions 即内置函数 dir(__builtins__) 可以查看所有的内置函数.注:pycharm中无法使用,不知道原因 help(input ...

  10. C# DateTime判断时间

    两种情况: 1 DateTime? dtTemp = null; if(dtTime != null) { //wawawa } 刚刚学会的,可空值类型,可判断是否赋值 2 DateTime dtTe ...