12.问题:如何通过java代码实现文件(图片为主)上传的功能?

解决方案:

第1步:下载并安装免费开源的支持FTP&SFTP的FTP服务器软件--FileZilla客户端。

https://download.filezilla-project.org/client/FileZilla3.41.1win64-setup_bundled.exe

第2步:远程登录Linux服务器通过yum命令安装vsftpd组件

yum -y install vsftpd

第3步:添加一个ftp用户,此用户就是用来登录ftp服务器用的

useradd ftpuser

第4步:给ftp用户添加密码

passwd ftpuser
结果输出为:
[root@hbs20190308 ~]# useradd ftpuser
[root@hbs20190308 ~]# passwd ftpuser
Changing password for user ftpuser.
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
注意密码要设置超过8个字符
New password: 
Retype new password: 
passwd: all authentication tokens updated successfully.
密码设置成功!
[root@hbs20190308 ~]# 

第5步:前往阿里云将Linux服务器的防火墙开启21端口

第6步:查看selinux状态

getsebool -a | grep ftp

注:如果是第一次配置,那么此处可能会报错

[root@hbs20190308 ~]# getsebool -a | grep ftp
getsebool:  SELinux is disabled
[root@hbs20190308 ~]# setsebool -P allow_ftpd_full_access on
setsebool:  SELinux is disabled.

错误原因:selinux被禁用

[root@hbs20190308 ~]# cd /etc/selinux
[root@hbs20190308 selinux]# ls
config  final  semanage.conf  targeted  tmp
[root@hbs20190308 selinux]# more config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

百度翻译结果:
#此文件控制系统上SELinux的状态。

#selinux=可以采用以下三个值之一:

#强制执行-已强制执行SELinux安全策略。

#允许-selinux打印警告而不是强制执行。

#已禁用-未加载SELinux策略。

SELinux=禁用

#selinuxtype=可以取三个值之一:

#目标-目标流程受到保护,

#最小-修改目标策略。仅保护选定的进程。

#MLS-多级安全保护。

selinuxtype=目标

第7步:修改selinux的配置

cd /etc/selinux
cp config config.2019.03.10
vim /etc/selinux/config
将"SELINUX=disabled"改为"SELINUX=permissive"
保存退出!

第8步:重启服务器

reboot

第9步:启动web容器,数据库和web服务器

启动tomcat
启动mysql
启动nginx

第10步:查看selinux状态

getsebool -a | grep ftp
结果输出为:
[root@hbs-20190306 ~]# getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
httpd_can_connect_ftp --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
tftp_home_dir --> off
[root@hbs-20190306 ~]# 

第11步:开启外网的访问vsftpd的权限

setsebool -P ftpd_full_access on
setsebool -P tftp_home_dir on

第12步:关闭匿名访问,开启被动模式

cd /etc/vsftpd
vim chroot_list
保存退出
cp vsftpd.conf vsftpd.conf.2019.03.10
vim vsftpd.conf
修改anonymous_enable=YES为NO
并在最后面添加
pasv_enable=YES
pasv_min_port=3000
pasv_max_port=5000
allow_writeable_chroot=YES
保存退出

第13步:设置开机启动vsftpd ftp服务

chkconfig vsftpd on

第14步:重启ftp服务:

service vsftpd restart

第15步:查看vsftpd服务进程是否正在运行..

ps -A|grep vsftpd

第16步:修改iptables的配置文件,如若不改则连接登录成功后读取不了列表

cd /etc/sysconfig
cp iptables-config iptables-config.2019.03.10
vim iptables-config
把 IPTABLES_MODULES="" 修改为:IPTABLES_MODULES="ip_nat_ftp"

保存退出

第17步:重启服务器

reboot

第18步:启动web容器,数据库和web服务器

启动tomcat
启动mysql
启动nginx

第19步:查看vsftpd服务进程是否正在运行..

ps -A|grep vsftpd

vsftpd.conf配置文件的全部内容

    # Example config file /etc/vsftpd/vsftpd.conf
    #
    # The default compiled in settings are fairly paranoid. This sample file
    # loosens things up a bit, to make the ftp daemon more usable.
    # Please see vsftpd.conf.5 for all compiled in defaults.
    #
    # READ THIS: This example file is NOT an exhaustive list of vsftpd options.
    # Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's
    # capabilities.
    #
    # Allow anonymous FTP? (Beware - allowed by default if you comment this out).
    anonymous_enable=NO
    #
    # Uncomment this to allow local users to log in.
    # When SELinux is enforcing check for SE bool ftp_home_dir
    local_enable=YES
    #
    # Uncomment this to enable any form of FTP write command.
    write_enable=YES
    #
    # Default umask for local users is 077. You may wish to change this to 022,
    # if your users expect that (022 is used by most other ftpd's)
    local_umask=022
    #
    # Uncomment this to allow the anonymous FTP user to upload files. This only
    # has an effect if the above global write enable is activated. Also, you will
    # obviously need to create a directory writable by the FTP user.
    # When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access
    #anon_upload_enable=YES
    #
    # Uncomment this if you want the anonymous FTP user to be able to create
    # new directories.
    #anon_mkdir_write_enable=YES
    #
    # Activate directory messages - messages given to remote users when they
    # go into a certain directory.
    dirmessage_enable=YES
    #
    # Activate logging of uploads/downloads.
    xferlog_enable=YES
    #
    # Make sure PORT transfer connections originate from port 20 (ftp-data).
    connect_from_port_20=YES
    #
    # If you want, you can arrange for uploaded anonymous files to be owned by
    # a different user. Note! Using "root" for uploaded files is not
    # recommended!
    #chown_uploads=YES
    #chown_username=whoever
    #
    # You may override where the log file goes if you like. The default is shown
    # below.
    #xferlog_file=/var/log/xferlog
    #
    # If you want, you can have your log file in standard ftpd xferlog format.
    # Note that the default log file location is /var/log/xferlog in this case.
    xferlog_std_format=YES
    #
    # You may change the default value for timing out an idle session.
    #idle_session_timeout=600
    #
    # You may change the default value for timing out a data connection.
    #data_connection_timeout=120
    #
    # It is recommended that you define on your system a unique user which the
    # ftp server can use as a totally isolated and unprivileged user.
    #nopriv_user=ftpsecure
    #
    # Enable this and the server will recognise asynchronous ABOR requests. Not
    # recommended for security (the code is non-trivial). Not enabling it,
    # however, may confuse older FTP clients.
    #async_abor_enable=YES
    #
    # By default the server will pretend to allow ASCII mode but in fact ignore
    # the request. Turn on the below options to have the server actually do ASCII
    # mangling on files when in ASCII mode. The vsftpd.conf(5) man page explains
    # the behaviour when these options are disabled.
    # Beware that on some FTP servers, ASCII support allows a denial of service
    # attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd
    # predicted this attack and has always been safe, reporting the size of the
    # raw file.
    # ASCII mangling is a horrible feature of the protocol.
    ascii_upload_enable=YES
    ascii_download_enable=YES
    #
    # You may fully customise the login banner string:
    ftpd_banner=Welcome to blah FTP service.
    #
    # You may specify a file of disallowed anonymous e-mail addresses. Apparently
    # useful for combatting certain DoS attacks.
    #deny_email_enable=YES
    # (default follows)
    #banned_email_file=/etc/vsftpd/banned_emails
    #
    # You may specify an explicit list of local users to chroot() to their home
    # directory. If chroot_local_user is YES, then this list becomes a list of
    # users to NOT chroot().
    # (Warning! chroot'ing can be very dangerous. If using chroot, make sure that
    # the user does not have write access to the top level directory within the
    # chroot)
    chroot_local_user=YES
    chroot_list_enable=YES
    # (default follows)
    chroot_list_file=/etc/vsftpd/chroot_list
    #
    # You may activate the "-R" option to the builtin ls. This is disabled by
    # default to avoid remote users being able to cause excessive I/O on large
    # sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
    # the presence of the "-R" option, so there is a strong case for enabling it.
    #ls_recurse_enable=YES
    #
    # When "listen" directive is enabled, vsftpd runs in standalone mode and
    # listens on IPv4 sockets. This directive cannot be used in conjunction
    # with the listen_ipv6 directive.
    listen=NO
    #
    # This directive enables listening on IPv6 sockets. By default, listening
    # on the IPv6 "any" address (::) will accept connections from both IPv6
    # and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6
    # sockets. If you want that (perhaps because you want to listen on specific
    # addresses) then you must run two copies of vsftpd with two configuration
    # files.
    # Make sure, that one of the listen options is commented !!
    listen_ipv6=YES

    pam_service_name=vsftpd
    userlist_enable=YES
    tcp_wrappers=YES

    anon_root=/home/ftpuser

    pasv_enable=YES
    pasv_min_port=3000
    pasv_max_port=5000

    allow_writeable_chroot=YES

第20步:打开FileZilla客户端,选择文件->站点管理器,开始创建连接登录到Linux服务器上的vsftpd,注意:因为Linux服务器端的vsftpd在第12步已经开启了被动模式,所以客户端的传输设置应该为被动模式(选择编辑->设置->FTP中修改传输设置为被动(推荐))!

结果输出为:
状态: 正在连接 47.106.215.100:21...
状态: 连接建立,等待欢迎消息...
状态: 已登录
状态: 读取目录列表...
状态: 服务器发回了不可路由的地址。使用服务器地址代替。
状态: 列出“/”的目录成功

第21步:创建一个Maven的jar工程,命名为FTP-Test,首先在pom.xml中添加依赖

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.hbs</groupId>
    <artifactId>FTP-Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <!-- 访问ftp服务器 -->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

第22步:在测试包com.hbs.test中新建一个测试类FTPClientTestCase,在该类中写一个测试方法,专门测试文件上传至Linux服务器中的vsftpd中(即ftp用户所在目录/home/ftpuser)

    @Test
    public void testFtp() throws Exception {
        //1、连接ftp服务器
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect("47.106.215.100", 21);// Linux服务器IP地址和端口号(ftp传输端口为21)
        //2、登录ftp服务器
        ftpClient.login("ftpuser", "hbs7827994");// Linux服务器中vsftpd的用户名和密码
        //3、读取本地文件
        File file=new File("F:\\html\\258.jpg");// 将要上传的文件所在的绝对路径
        FileInputStream inputStream = new FileInputStream(file);
        //4、上传文件
        //1)指定上传目录
        ftpClient.changeWorkingDirectory("/home/ftpuser/");// 将要上传的目标目录
        //2)指定文件类型
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        //第一个参数:文件在远程服务器的名称
        //第二个参数:文件流
        ftpClient.storeFile(file.getName(), inputStream);// 执行上传
        System.out.println("图片上传成功!");
        //5、退出登录
        ftpClient.logout();
    }

第23步:另外还需要在nginx的配置文件/usr/local/nginx/nginx.conf中修改root路径指向/home/ftpuser(即把nginx的根目录指向ftp上传文件的目录),然后重新加载配置文件(nginx -s reload)