java 跨服务器上传,下载,预览,删除

1 篇文章 0 订阅

跨服务器上传需要用到第三方辅助,这里使用的是ftp服务器,它可以帮助我们上传下载删除文件

假如我们的项目部署在了A服务器,需要上传的的文件到B服务器就需要使用ftp 服务器来帮助了

1. 首先,我们需要在B服务器下载ftp服务器
yum install -y vsftpd
2.查看状态
systemctl status vsftpd.service
3.启动ftp
 systemctl start vsftpd.service
4.关闭ftp
systemctl start vsftpd.service
5.修改配置文件
vim /etc/vsftpd/vsftpd.conf
6.
不允许匿名登录 将YES改成NO
anonymous_enable=NO
设置登录地址,添加以下目录,登录后的默认路径
local_root=/apps/lims/lims-be/static

也可以限制某个用户的访问权限

java 代码

pom
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.8.0</version>
        </dependency>

代码

登录
import com.yssoo.lims.modules.core.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.IOException;

/**
 * @author :si
 * @date :2023/2/17
 */
@Slf4j
public class FtpUtil {
    /**
     * 登录  和liunx 账号密码一致即可,也可以单独设置
     * @param server ip
     * @param port  端口
     * @param user 账号
     * @param password 密码
     * @return 是否登录成功
     */
    public static FTPClient login(String server, Integer port, String user, String password) {
        // 创建FTPClient对象
        FTPClient ftpClient = new FTPClient();
        try {
            // 连接FTP服务器
            ftpClient.connect(server, port);
            // 登录FTP服务器
            ftpClient.login(user, password);
            // 获取FTP服务器的响应码
            int replyCode = ftpClient.getReplyCode();
            // 如果响应码不是“正常”,返回
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.debug("server{}", "port{}", "user{}", "pwd{}", server, port, user, password);
                throw new BusinessException("ftp登入失败");
            }
            // 设置被动模式(passive mode)
            ftpClient.enterLocalPassiveMode();
            // 设置文件传输类型为二进制文件类型
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftpClient;
    }

    public static void ftpFinally(FTPClient ftpClient) {
        // 关闭FTP连接
        if (ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

上传

import org.apache.commons.net.ftp.FTPClient;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author :si
 * @date :2023/2/17
 */
public class FtpUpload {
    /**
     * 上传
     * @param ftpClient ftp客户端
     * @param remoteFile 远程文件名
     * @param localFileName 本地文件流
     * @return 是否成功
     */
    public static Boolean upload(
            FTPClient ftpClient, String remoteFile, InputStream localFileName) {
        try {
            return ftpClient.storeFile(remoteFile, localFileName);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

预览和下载(区别在于,预览图片文本之类的可以直接在浏览器观看,下载就是下载到本地了,如果不是文本之类的俩都可以下载)

import com.yssoo.lims.modules.core.exception.BusinessException;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @author :si
 * @date :2023/2/17
 */
public class FtpDownload {
    /**
     * 预览
     * @param ftpClient ftp客户端
     * @param response 相应
     * @param remoteFile 远程文件名
     */
    
    public static void previewArea(FTPClient ftpClient, HttpServletResponse response,String remoteFile){
        // 获取远程文件的输入流
        try (OutputStream outputStream = response.getOutputStream();
             InputStream inputStream = ftpClient.retrieveFileStream(remoteFile)) {
            // 如果远程文件不存在,返回
            if (inputStream == null) {
                return;
            }
            // 将远程文件的内容写入HTTP响应中
            byte[] buffer = new byte[1024];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载
     * @param ftpClient ftp 客户端
     * @param response 响应
     * @param remoteFile 远程文件路径
     * @param remoteName 远程文件名
     */
    public static void downLoad(FTPClient ftpClient, HttpServletResponse response,String remoteFile,String remoteName){
        // 下载文件
        InputStream inputStream;
        try {
            inputStream = ftpClient.retrieveFileStream("/" + remoteFile);
            if (inputStream == null) {
                response.setStatus(HttpStatus.NOT_FOUND.value());
                throw new BusinessException("下载失败");
            }
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + remoteName);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                // 输出到浏览器响应
                response.getOutputStream().write(buffer, 0, len);
            }
            inputStream.close();
            ftpClient.logout();
            response.getOutputStream().flush();
        } catch (IOException e) {
        e.printStackTrace();
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
    }

    }
}

删除

import org.apache.commons.net.ftp.FTPClient;
import java.io.IOException;

/**
 * @author :si
 * @date :2023/2/20
 */
public class FtpDel {
    /**
     * 删除
     * @param ftpClient ftp 客户端
     * @param remoteFilePath 远程文件路径(路径+文件名)
     * @return 是否成功
     */
    public static boolean delFile(FTPClient ftpClient, String remoteFilePath) {
        ftpClient.enterLocalPassiveMode();
        try {
            return ftpClient.deleteFile(remoteFilePath);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}
controller 层

 /** 这个作用在 删除、下载、预览的路径上, /** 后面就是文件名
     * 把指定URL后的字符串全部截断当成参数 这么做是为了防止URL中包含中文或者特殊字符(/等)时,匹配不了的问题
     *
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path =
                (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern =
                (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }

 /**
     * 处理上传文件请求
     *
     * @param file 上传的文件
     * @return 返回上传结果,url
     */
    @PostMapping("/ftp/upload")
    public R handleFileUpload(@RequestParam("file") MultipartFile file) {

        return R.ok(
                storageService.upload(
                        ftpProperties.getServer(),
                        ftpProperties.getPort(),
                        ftpProperties.getUser(),
                        ftpProperties.getPassword(),
                        file));
    }

    /**
     * 处理预览文件请求
     *
     * @param response HTTP响应对象
     * @param request HTTP请求
     */
    @GetMapping("/ftp/static/**")
    public void previewArea(HttpServletRequest request, HttpServletResponse response) {
        String remoteFile = extractPathFromPattern(request);
        FTPClient ftpClient =
                storageService.download(
                        ftpProperties.getServer(),
                        ftpProperties.getPort(),
                        ftpProperties.getUser(),
                        ftpProperties.getPassword());
        FtpDownload.previewArea(ftpClient, response, remoteFile);
        FtpUtil.ftpFinally(ftpClient);
        R.ok();
    }
    /**
     * 处理下载文件请求
     *
     * @param response HTTP响应对象
     * @param request HTTP请求
     */
    @GetMapping("/ftp/download/**")
    public void handleFileDownload(HttpServletRequest request, HttpServletResponse response) {
        String remoteName = extractPathFromPattern(request);
        log.info("downloadFile:{}", remoteName);
        FTPClient ftpClient =
                storageService.download(
                        ftpProperties.getServer(),
                        ftpProperties.getPort(),
                        ftpProperties.getUser(),
                        ftpProperties.getPassword());
        FtpDownload.downLoad(
                ftpClient,
                response,
                ftpProperties.getDownLoadPath() + "/" + remoteName,
                remoteName);
        FtpUtil.ftpFinally(ftpClient);
        R.ok();
    }

    /**
     * 处理删除文件请求
     *
     * @param request HTTP请求
     */
    @DeleteMapping("/ftp/del/**")
    public R deleteFile(HttpServletRequest request) {
        String remoteName = extractPathFromPattern(request);
        log.info("delFile:{}", remoteName);
        FTPClient ftpClient =
                storageService.download(
                        ftpProperties.getServer(),
                        ftpProperties.getPort(),
                        ftpProperties.getUser(),
                        ftpProperties.getPassword());
        boolean delFile =
                FtpDel.delFile(ftpClient, ftpProperties.getDownLoadPath() + "/" + remoteName);
        FtpUtil.ftpFinally(ftpClient);
        return R.ok(delFile);
    }
service层
 @Override
    public String upload(
            String server, int port, String user, String password, MultipartFile file) {
        FTPClient ftpClient = FtpUtil.login(server, port, user, password);
        String remoteFile = generateKeyByDate(file.getOriginalFilename());

        Boolean upload;
        try {
            upload = FtpUpload.upload(ftpClient, remoteFile,file.getInputStream());
            if (!upload) {
                throw new BusinessException("上传文件失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        FtpUtil.ftpFinally(ftpClient);

        return remoteFile;
    }

    @Override
    public FTPClient download(String server, int port, String user, String password) {
        return FtpUtil.login(server, port, user, password);
    }

基本都在controller完成了,因为项目结构很乱,你们可以随意。

这个在yml中定义了,直接取就可以了
@Component
@ConfigurationProperties(prefix = "ftp")
@Data
public class FtpProperties {
    private  String server;
    private  int port;
    private  String user;
    private  String password;
    private  String downLoadPath;
}
yml

ftp:
  port: 21
  server: 1.1.1.224
  user: root
  password: root
  down-load-path: /user/loacl

即可

上述下载超过100M可能会断开链接,以下亲测可以下载500+ 最大多数不清楚,可以适当扩大读取数据

public static void downLoad(
            FTPClient ftpClient,
            HttpServletResponse response,
            String remoteFile,
            String remoteName) {

        ServletOutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            // 获取输入流
            inputStream = ftpClient.retrieveFileStream(remoteFile);
            // 设置响应头信息
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + remoteName);
            // 获取响应输出流
            outputStream = response.getOutputStream();
            // 写入数据到响应输出流
            // 每次读取1MB数据
            byte[] buffer = new byte[1024 * 1024];
            // 设置缓冲区大小为1MB
            ftpClient.setBufferSize(1024 * 1024);
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值