FTP文件上传

前言

以前写ftp上传使用buff上传append拼接,今天使用了循环拼接,但是缺点确实不能flush
总结一下,以备后用


引入依赖

commons-net-1.4.1.jar

maven下载

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>1.4.1</version>
</dependency>

自定义FTP工具类



import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.SocketException;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;

/**
 * 〈FTP工具类〉<br>
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
public class FTPUtil {

    private FTPClient ftpClient;

    public static final int BINARY_FILE_TYPE = FTP.BINARY_FILE_TYPE;

    public static final int ASCII_FILE_TYPE = FTP.ASCII_FILE_TYPE;

    static Logger logger = org.slf4j.LoggerFactory.getLogger(FTPUtil.class);

    /**
     * 使用详细信息进行ftp服务器连接: <br>
     * 〈功能详细描述〉
     *
     * @param host :服务器地址名称
     * @param port :端口号
     * @param user :用户名
     * @param password :appendFile
     * @param path :转移到FTP服务器目录
     * @throws SocketException
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void connectServer(String host, int port, String user, String password, String path) throws SocketException,
            IOException {
        ftpClient = new FTPClient();
        ftpClient.connect(host, port);
        ftpClient.login(user, password);
        if (path != null && path.length() != 0) {

            boolean changeok = ftpClient.changeWorkingDirectory(path);
            if (!changeok) {
                // 变更目录失败,生成目录
                ftpClient.mkd(path);
                ftpClient.changeWorkingDirectory(path);
            }
        }
        ftpClient.setBufferSize(1024);// 设置上传缓存大小
        ftpClient.setControlEncoding("UTF-8");// 设置编码
        ftpClient.setFileType(BINARY_FILE_TYPE);// 设置文件类型
    }

    /**
     * 关闭连接
     * 
     * @throws IOException
     */
    public void closeServer() throws IOException {
        if (ftpClient != null && ftpClient.isConnected()) {
            ftpClient.logout();// 退出FTP服务器
            ftpClient.disconnect();// 关闭FTP连接
        }
    }

    /**
     * 删除服务器上的文件
     * 
     * @param pathName
     * @return
     * @throws IOException
     */
    public boolean deleteFile(String pathName) throws IOException {
        return ftpClient.deleteFile(pathName);
    }

    /**
     * 以流的方式上传文件到ftp服务器: <br>
     * 〈功能详细描述〉
     *
     * @param iStream :输入流
     * @param remoteFileName :上传到服务器的文件名称
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public boolean uploadFile(InputStream iStream, String remoteFileName) throws IOException {
        boolean flag = false;
        try {
            // 将文件名转码,防止中文文件名上传失败失败问题,
            flag = ftpClient.storeFile(new String(remoteFileName.getBytes("UTF-8"), "iso-8859-1"), iStream);
        } catch (IOException e) {
            flag = false;
            logger.error("uploadFile 文件转码失败 :" + e);
            return flag;
        } finally {
            if (iStream != null) {
                iStream.close();
            }
        }
        return flag;
    }

	//追加写入
    public boolean appendFile(String remote, InputStream local) throws IOException {
        return ftpClient.appendFile(remote, local);
    }

	//获取写入流
    public Writer getRemoteFileWriter (String remoteFileName) throws IOException {
        OutputStreamWriter writer  = null;
        try {

            writer = new OutputStreamWriter(ftpClient.appendFileStream(remoteFileName));
 /*
         BufferedWriter bw = new BufferedWriter(out);
         bw.write("\n"+versionCode+path);
            bw.flush();
            bw.close();
            out.close();*/

        } catch (IOException e) {
            return null;
        }
        return writer;

    }

    /**
     * 从ftp服务器上下载文件到本地输入流: <br>
     * 〈功能详细描述〉
     *
     * @param sourceFileName :服务器资源文件名称
     * @param oStream :本地输入流
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public void retrieveFile(String sourceFileName, OutputStream oStream) throws IOException {
        ftpClient.retrieveFile(new String(sourceFileName.getBytes("UTF-8"), "iso-8859-1"), oStream);
    }

    /**
     * 上传文件,从ftp服务器上拿到OutputStream,往流中写入数据: <br>
     * 〈功能详细描述〉
     *
     * @param remoteFileName
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public OutputStream storeUniqueFileStream(String remoteFileName) throws IOException {
        OutputStream oStream = ftpClient.storeUniqueFileStream(remoteFileName);
        return oStream;
    }

// 下载ftp上面的文件,自定义下载文件名称	、
    public void downLoad(String remoteFileName, String fileName) {
        try {
            ftpClient.retrieveFile("/" + remoteFileName, new FileOutputStream(fileName));
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage(), e);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * 从ftp服务器上获取上传的文件 <br>
     * 〈功能详细描述〉
     *
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public List<FTPFile> getListFiles(String ftpFilePath) {
        try {
            List<FTPFile> fileList = Arrays.asList(ftpClient.listFiles(ftpFilePath));
            return fileList;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

}


上传文件

public void uploadFileTest() {
		 // 要写入的文件内容
 	String fileContent = "hello world,你好世界";
 	// 创建的文件
 	String fileName = "ftp.txt";

 	 // ftp服务器地址
    @Value("${ftp.host}")
    private String host;
    // ftp端口号
    @Value("${ftp.port}")
    private int port;
    // ftp用户名称
    @Value("${ftp.username}")
    private String username;
    // ftp密码
    @Value("${ftp.pwd}")
    private String pwd;
    // ftp工作目录
    @Value("${ftp.wdtrade.location}")
    private String location;
 
		 FTPUtil ftpUtil = new FTPUtil();
 		try {
 			//连接ftp
            ftpUtil.connectServer(host, port, username, pwd, location);
            // 写入文件
            ftpUtil.uploadFile(new ByteArrayInputStream(fileContent.getBytes()), fileName );
 		} finally {
 			if (ftpClient.isConnected()) {
 				try {
 					ftpClient.disconnect();
 				} catch (Exception e) {
 					e.printStackTrace();
 				}
 			}
 		}
 	}


文件下载

	//服务器上获取文件名 或者页面传过来文件名
  String fileUrl = request.getParameter("fileUrl");  
  response.setContentType("application/x-download");
  response.addHeader("Content-Disposition", "attachment;filename=" + fileUrl);
OutputStream os = response.getOutputStream()
    FTPUtil ftpUtil = new FTPUtil();
        logger.info("从服务器{}获取文件{},{}", host, fileName);
        try {
            // 连接FTP服务器
            ftpUtil.connectServer(host, port, username, pwd, location);// 连接ftp服务器
            // 开始读取文件到浏览器
            ftpUtil.retrieveFile(fileName, os);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BizFailException(ErrorCodeConstants.NOT_FOUND, "ftp上没有上传的文件");
        } finally {
            try {
                // 关闭流
                os.close();
            } catch (IOException e) {
                logger.error("关闭os流失败{}", e);
            }
            try {
                // 释放FTP连接
                ftpUtil.closeServer();
            } catch (IOException e) {
                logger.error("关闭ftp服务失败{}", e);
            }
        }


    }











第一种写法

jdk自带换行符: System.getProperty(“line.separator”)

这也是换行符,功能和"\n"是一致的,但是此种写法屏蔽了 Windows和Linux的区别 ,更保险一些.

//换行符加上bytes格式

try{
		//连接
ftpUtil.connectServer(host, port, username, pwd, location);
String head = CSVUtil.joinByLineSeparator(Arrays.asList(CSVUtil.joinByCommas(new String[] { "xxx", "xxx", "xxx" })));
            // 上传文件头
ftpUtil.uploadFile(new ByteArrayInputStream(head.getBytes()), 文件名);

  	//获取成字节
 byte[] csvBytes = (System.getProperty("line.separator") + wirteInforList(resultWirtList)).getBytes();
 
 boolean isSuccess = ftpUtil.appendFile(文件名,
                            new ByteArrayInputStream(csvBytes));
                            
if (!isSuccess) {
 logger.error("--------追加数据失败--------------");
return false;
                    }


private String wirteInforList(List<ConsumptionInfoDto> resultWirtList) throws IOException {

        List<String> exchangeOrderRows = map(new Function<ConsumptionInfoDto, String>() {
            @Override
            public String apply(ConsumptionInfoDto consumptionInfoDto) {
                return CSVUtil.joinByCommas(convertNull(Arrays.asList(consumptionInfoDto.getCardNo() + "\t",
                        consumptionInfoDto.getBizOrderNo() + "\t", consumptionInfoDto.getPartnerOrderNo() + "\t",
                        new SimpleDateFormat("yyyy-MM-dd").format(consumptionInfoDto.getTradeTime()) + "\t",
                        consumptionInfoDto.getWdCardNo() + "\t", consumptionInfoDto.getWdStoreCode() + "\t")));
            }
        }, resultWirtList);

        return CSVUtil.joinByLineSeparator(Arrays.asList(CSVUtil.joinByLineSeparator(exchangeOrderRows)));

    }
   }catch (Exception e) {
                logger.error("上传FTP失败", e);
                return false;
            } finally {
                try {
                    ftpUtil.closeServer();
                } catch (IOException e) {
                    logger.error("IO异常", e);
                }
            }



    // 转换工具类 CSV
    static class CSVUtil {

        static String joinByCommas(String[] cols) {
            List<String> colList = Arrays.asList(cols);
            return joinByCommas(colList);
        }

        static String joinByCommas(List<String> colList) {

            return join(colList, ",");
        }

        static String joinByLineSeparator(String[] lines) {
            List<String> lineList = Arrays.asList(lines);
            return joinByLineSeparator(lineList);
        }

        static String joinByLineSeparator(List<String> lineList) {
            return join(lineList, System.getProperty("line.separator"));
        }

        static String join(List<String> strList, String separator) {
            if (CollectionUtils.isEmpty(strList)) {
                return "";
            } else if (strList.size() > 1) {
                String first = StringUtils.isNotEmpty(strList.get(0)) ? strList.get(0) : "";
                return first.concat(separator).concat(join(strList.subList(1, strList.size()), separator));
            } else {
                return strList.get(0);
            }
        }

    }

    // 定义map
    static <I, O> List<O> map(Function<I, O> function, List<I> iList) {
        List<O> oList = new ArrayList<O>();
        if (CollectionUtils.isEmpty(iList)) {
            return oList;
        }
        for (I input : iList) {
            O output = function.apply(input);
            oList.add(output);
        }
        return oList;
    }

    // 定义接口
    interface Function<I, O> {
        O apply(I input);
    }

    // 定义如果为空那么设置为空字符串
    private List<String> convertNull(List<String> list) {
        List<String> listStr = new ArrayList<String>();
        for (String str : list) {
            if (str.equals(null + "\t")) {
                str = " ";
            }
            listStr.add(str);
        }
        return listStr;

    }

这种写法比较简洁,把工具类封装一下,System.getProperty(“line.separator”)再封装为字符串,非常简洁干净但是唯一缺点不好flush


第二种写法

    private boolean executeUpload(final WdTradeBatch wdTradeBatch) {
        // 连接ftp
        FTPUtil ftpUtil = new FTPUtil();
        OutputStream os = null;
        BufferedWriter bw = null;
        try {
            // step 5 :连接ftp
            ftpUtil.connectServer(host, port, username, pwd, location);

            // 原批次如果失败,删除原文件
            if (FAIL.equals(wdTradeBatch.getStatus())) {
                boolean delRes = ftpUtil.deleteFile(wdTradeBatch.getFileUrl());
                if (!delRes) {
                    throw new BizFailException("文件删除失败");
                }
            }
            os = ftpUtil.getRemoteFileOs(wdTradeBatch.getFileUrl());
            bw = new BufferedWriter(new OutputStreamWriter(os));

            // 上传文件头
            String head = new String(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF })
                    + CSVUtil.joinByLineSeparator(Arrays.asList(CSVUtil.joinByCommas(new String[] {  "xxx", "xxx", "xxx"  })));
            bw.write(head);

            //ftpUtil.uploadFile(new ByteArrayInputStream(head.getBytes()), wdTradeBatch.getFileUrl());
            // 上传文件详情数据
            return consumptionRecordUpload(bw, wdTradeBatch);

        } catch (Exception e) {
            logger.error("上传FTP失败", e);
            return false;
        } finally {
            try {
                bw.close();
                os.close();
                ftpUtil.closeServer();
            } catch (IOException e) {
                logger.error("IO异常", e);
            }
        }

    }


    private boolean consumptionRecordUpload(BufferedWriter bw,WdTradeBatch wdTradeBatch) throws IOException {
ArrayList<x> resultWirtList = new ArrayList<x>();
				while (true){

resultWirtList .add(1);

 					   if (resultWirtList.size() >= 100) {
                        String content = System.getProperty("line.separator") + wirteInforList(resultWirtList);
                        bw.write(content);
                        bw.flush();
                        resultWirtList = new ArrayList<ConsumptionInfoDto>();

}

			  if (CollectionUtils.isNotEmpty(resultWirtList)) {
                String content = System.getProperty("line.separator") + wirteInforList(resultWirtList);
                bw.write(content);
                bw.flush();
            }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值