springboot上传文件到ftp服务器(完美版)

话不多说,其实两年前我就改写这篇博客的。怪我自己。

最近又需要连接下内网的ftp服务器上传文件,找了下两年前的相似项目没找到,无奈只能网上找资料。网上的大多相似,确实能实现功能。下面看我的做法:

一、连接ftp

1.加入依赖

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

2.配置类

@Data
@Slf4j
@Service
public class FTPUtil {

    @Value("${ftp_ip}")
    private String ftpIp;
    @Value("${ftp_port}")
    private Integer ftpPort;
    @Value("${ftp_user}")
    private String ftpUser;
    @Value("${ftp_pass}")
    private String ftpPass;

    private FTPClient ftpClient;

    private boolean connectServer(String ip,int port,String user,String pwd){
        ftpClient=new FTPClient();
        Boolean isSuccess=false;
        try {
            ftpClient.connect(ip);
            isSuccess=ftpClient.login(user,pwd);
        } catch (IOException e) {
            log.error("连接ftp服务器失败",e);
        }
        return isSuccess;
    }

    public boolean uploadFile(String remotePath, List<File>fileList) throws IOException {
        boolean upload=true;
        FileInputStream fileInputStream=null;
        //connect to ftpServer
        if (connectServer(ftpIp,ftpPort,ftpUser,ftpPass)){
            try {
                ftpClient.changeWorkingDirectory(remotePath);
                ftpClient.setBufferSize(1024);
                ftpClient.setControlEncoding("UTF-8");
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.enterLocalPassiveMode();
                for (File fileItem:fileList
                        ) {
                    fileInputStream=new FileInputStream(fileItem);
                    ftpClient.storeFile(fileItem.getName(),fileInputStream);
                }
            } catch (IOException e) {
                log.error("上传文件异常",e);
                upload=false;
            }finally {
                fileInputStream.close();
                ftpClient.disconnect();
            }
        }
        return upload;
    }

    public boolean uploadToFtp(String remotePath, String fileName, File file) throws IOException {
        boolean upload = true;
        FileInputStream fileInputStream = null;
        //connect to ftpServer
        if (connectServer(ftpIp, ftpPort, ftpUser, ftpPass)) {
            try {
                ftpClient.changeWorkingDirectory(remotePath);
                ftpClient.setBufferSize(1024);
                ftpClient.setControlEncoding("UTF-8");
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.enterLocalPassiveMode();

                //上传文件 参数:上传后的文件名,输入流
                upload = ftpClient.storeFile(fileName, new FileInputStream(file));
            } catch (IOException e) {
                log.error("上传文件异常", e);
                upload = false;
            } finally {
                if(StringUtil.isPresent(fileInputStream)) fileInputStream.close();
                ftpClient.disconnect();
            }
        }
        return upload;
    }
}

配置类这块同学们记得把ftpIp、ftpPort、ftpUser、ftpPass这几个在配置文件配好,默认port都是21。

二、上传文件

1.直接看代码

@Override
public String uploadFileToFtp(MultipartFile[] fileList) throws Exception {

    //1、获取原文件后缀名
    MultipartFile multipartFile = fileList[0];
    String originalFileName = multipartFile.getOriginalFilename();
    String suffix = originalFileName.substring(originalFileName.lastIndexOf('.'));

    //2、使用UUID生成新文件名
    String newFileName = UUID.randomUUID() + suffix;

    //3、将MultipartFile转化为File
    File file = FileUtil.multipartFileToFile(multipartFile);

    //4、上传至ftp服务器
    if (ftpUtil.uploadToFtp(ftpUploadPath, newFileName, file)) {
        System.out.println("上传至ftp服务器!");
    } else {
        System.out.println("上传至ftp服务器失败!");
    }
    return getFtpUrl(ftpUploadPath, newFileName);
}

2.工具类

public static File multipartFileToFile(MultipartFile file) throws Exception {

    File toFile = null;
    if (file.equals("") || file.getSize() <= 0) {
        file = null;
    } else {
        InputStream ins = null;
        ins = file.getInputStream();
        toFile = new File(file.getOriginalFilename());
        inputStreamToFile(ins, toFile);
        ins.close();
    }
    return toFile;
}

//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
    try {
        OutputStream os = new FileOutputStream(file);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2.说明(重点)

    1.大家看ftpUtil.uploadToFtp(ftpUploadPath, newFileName, file)这句话,其实就是掉的上面配置类的方法,ftpUploadPath是你ftp上要上传文件的路径,newFileName是重新生成的文件名,file就是你获取的文件。

    2.最初大家得到的都是MultipartFile或者MultipartFile[],我看网上的都是将它又重新在本地生成个文件,这不是多此一举嘛,你都拿到需要的文件了,又给它多生成一遍是要干啥?最让我气的是网上的博客大多是这样写的,千篇一律的复制,误人子弟。。。

    3.大家看配置类中的uploadToFtp方法,最主要的就是ftpClient.storeFile(fileName, new FileInputStream(file));这句。他最终上传的就是FileInputStream这个玩意,其实我上面的代码还可以简化哈,直接将MultipartFile转化成FileInputStream。

三、注意点

1.先确保连接上ftp,connectServer这个返回true。如果返回false,检查ip,port,user,pass。还有防火墙。
2.ftpClient.setControlEncoding(“UTF-8”);中文路径记得加这个
3.ftpClient.enterLocalPassiveMode();被动模式,如果ftp服务器设置了记得加上
4. ftpClient.storeFile返回false的可能:
    1.路径没写对
    2.没有ftp上文件的操作权限

四、总结

总结:觉得写得不错的点个赞就知足了。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐