我的情况是利用宝塔面板,将新建FTP 和 本地文件链接

一.上传

1. 新建上传目录

在根目录下,新建/www/upload/,作为上传目标地址

2. 新建FTP

解决宝塔docker上传大文件超时问题_端口号

其中

  • 根目录要指定之前建立的目录
  • TCP控制连接端口21,默认的协议端口,
  • 20:主动模式数据端口
  • 39000~40000:被动模端口范围
    这几个端口需要在防火墙中放行,
    使用命令firewall-cmd --zone=public --add-port=20/tcp --permanent开启端口
    查看已打开的端口:firewall-cmd --list-ports
3. Java实现

Maven依赖添加

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

然后在文件上传工具类中添加功能实现代码

public String upload(MultipartFile uploadFile) {
        //创建客户端对象
        FTPClient ftp = new FTPClient();
        //文件输出流
        InputStream inputStream=null;
        try {
            //ip+端口=连接ftp服务器
            ftp.connect("xx.xx.xx.xx",21);
            //登录:输入新增FTP时设置的用户名和密码
            ftp.login("admin","admin");
            //上传路径
            String path = "/www/upload/";
            //检测该路径是否存在,若不存在便新建此路径
            boolean b = ftp.changeWorkingDirectory(path);
            if(!b) {
                ftp.makeDirectory(path);
            }
            //制定上传路径
            ftp.changeWorkingDirectory(path);
            //指定上传文件的类型为二进制文件
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            //获取文件输入流
             inputStream= uploadFile.getInputStream();
            //得到源文件名
            String oldName = uploadFile.getOriginalFilename();
            //利用时间戳生成新的文件名
            String filename = String.valueOf(new Date().getTime()) + oldName.substring(oldName.lastIndexOf("."));
            //上传
            ftp.storeFile(filename,inputStream);
            //返回文件名
            return filename;
        } catch (SocketException e) {
        	System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
      		System.out.println(e.getMessage());
            e.printStackTrace();
        }finally {
            try {
                //关闭文件流
                inputStream.close();
                //退出
                ftp.logout();
                //断开连接
                ftp.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "没有么";
    }

页面中可以这样

<form action="Controller访问路径" id="combined_tasks_form" method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="submit" value="上传"/>
</form>
//必须设置属性enctype="multipart/form-data"

OK,经过上面这几步操作,我们就可以成功的将文件上传到服务器的/www/upolad文件下了。

若是不成功,可以看看上传目标文件夹是否有读写权限。查看upload文件夹的权限

解决宝塔docker上传大文件超时问题_上传_02


改为可写入即可。

二、访问上传后的文件

1.通过ftp直接下载

FTP是文件传输协议,我们再次通过访问该ftp路径,即可下载服务器中的文件
例如:ftp://admin:admin@xx.xx.xx.xx/index.html就可以下载此html文档了。

通过http请求仅查看

查看的话,就要将磁盘路径映射到网络地址,所以我们可以新建一个网站站点

解决宝塔docker上传大文件超时问题_端口号_03


在这里新建一个站点,

解决宝塔docker上传大文件超时问题_服务器_04

  • 域名:如果没有域名,可以填写ip
  • 根目录:要映射到之前上传文件的目录,如我的:/www/upload
  • 端口默认为80,所以要打开80口的防火墙访问

都做好后,就可以通过
http://xx.xx.xx.xx:80/index.html访问资源了。

更新

通过上面的工作,localhost本地运行是没有问题的。
如果将项目部署到服务器,会出现无法上传的问题。
解决方法
再文件传送前面添加

ftp.enterLocalPassiveMode();
ftp.storeFile(filename,local);

原因:
根据数据连接是否是服务器端主动建立,FTP有主动和被动两种模式

  • 主动模式:服务器端主动建立数据连接,其中服务器端的端口号为 20,客户端的端口号随机,但是必须大于 1024,因为 0~1023 是熟知端口号
  • 被动模式:客户端主动建立数据连接,其中客户端的端口号由客户端自己指定,服务器端的端口号随机
    所以当客户端主动建立连接,服务器的端口号随机,这个随机的端口号可能并没有被开启,造成连接失败,上传失败。