前言
一般开发中, 都会把图片上传到一个目录, 然后将目录和文件名拼接存储在数据库中, 但是, 这种方法如果没弄好的话可能有一定的缺陷.
若项目搬迁, 即时这台服务器本身还在用, 存放在服务器的跟项目相关的图片也要跟着搬迁, 同时还要修改代码, 会造成较多麻烦. 如果搭建一个专门存放图片的服务器, 而且通过 ftp 传输, 那么你的代码就不用改了.
关于 Docker 和 Nginx 的介绍和优点在这里就不展开了, 网上博客和教程也有很多.
环境搭建
环境搭建有些模块可能不够详细, 如果想知道更多的话可以查看其他资料, 这里只是简单操作.
1, 安装 Docker
yum install docker
2, 拉取 Nginx 镜像
docker pull nginx:1.16.0
1.16.0 是版本号, 可以通过 docker search nginx 查询镜像; 拉取其他镜像比如 tomcat,MySQL 等同理.
3, 创建主要文件, 用于 docker 挂载
mkdir -p /home/nginx/www /home/nginx/logs /home/nginx/conf
4, 创建并运行 Nginx 容器
- docker run -d -p 80:80 -p 443:443 --name nginx-server -v /home/nginx/www:/usr/share/nginx/html
- -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/nginx/logs:/var/log/nginx nginx
5, 在宿主机上创建 Nginx 的配置文件
在 / home/nginx/conf 中新建文件 nginx.conf, 并写入如下配置:
- user root;
- worker_processes 1;
- error_log /var/log/nginx/error.log warn;
- pid /var/run/nginx.pid;
- events {
- worker_connections 1024;
- }
- http {
- include /etc/nginx/mime.types;
- default_type application/octet-stream;
- log_format main '$remote_addr - $remote_user [$time_local]"$request" '
- '$status $body_bytes_sent"$http_referer" '
- '"$http_user_agent" "$http_x_forwarded_for"';
- access_log /var/log/nginx/access.log main;
- sendfile on;
- #tcp_nopush on;
- keepalive_timeout 65;
- #gzip on;
- include /etc/nginx/conf.d/*.conf;
- server {
- listen 443 ssl;
server_name 你的 ip 地址或域名;
root /usr/share/nginx/HTML;
ssl_certificate 你的密钥. pem;
ssl_certificate_key 你的密钥. key;
- ssl_session_timeout 5m;
- ssl_session_cache shared:SSL:1m;
- ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:aNULL:!MD5:!ADH:!RC4;
- ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
- ssl_prefer_server_ciphers on;
- # 跳转到 8080 端口, 即我的 tomcat 容器, 如果浏览器输入 https://ip/ 则跳转到 tomcat 容器 (已经运行并映射端口号)
- location / {
- root /usr/share/nginx/HTML;
- proxy_pass http://ip:8080/;
- index index.HTML index.htm;
- }
- # 如果浏览器输入 https://ip/images/ 则对应宿主机上的 /home/nginx/www/images/ 因为前面已经挂载了, 即宿主机某个目录和 docker 容器内的某个文件夹共享数据
- # 要先在宿主机的 /home/nginx/www/ 中创建 images 目录
- location ~ /images/ {
- root /usr/share/nginx/HTML/;
- }
- }
- server {
- listen 80;
server_name 你的 ip 地址或域名;
- rewrite ^ https://$host$1 permanent;
- }
- }
这里面有关于 ssl 的配置, 你需要先申请域名, 然后搞个 ssl 证书, 再进行配置, 这里也不做详细介绍.
环境配置差不多完成, 接下来安装 vsftpd 搭建 ftp
搭建 FTP
安装 vsftpd
yum -y install vsftpd
添加用户
useradd 自定义用户名
passwd 自定义密码
修改配置文件
vi /etc/vsftpd/vsftpd.conf
需要修改的地方如下:
- # 配置文件默认为 YES, 即支持匿名访问, 设置为不支持
- anonymous_enable=NO
- # 在最后添加这两行
- pasv_min_port=30000
- pasv_max_port=30009
保存退出后设置用户访问权限
- chown ftpadmin /home/nginx/www/image
- chmod 777 -R /home/nginx/www/image
完事后测试一波, 通过 ftp 上传后, 通过浏览器 https 请求得到如下结果:
* 补充一点: 阿里云服务器的话记得配置安全组, 将 21 号端口打开, 以及 443,80 端口, 还有 30000-30009 端口
Java 实现 FTP 传输
先在 resource 中创建 ftpResource.properties 文件, 并写入参数
FTP_ADDRESS = 你的 IP
FTP_PORT=21
FTP_USERNAME = 用户名
FTP_PASSWORD = 用户密码
- FTP_BASE_PATH=/home/nginx/www/images
- IMAGE_BASE_URL=https:// 域名 / images/
之后写一个工具类, 用于 FTP 传输
- import org.apache.commons.NET.ftp.FTP;
- import org.apache.commons.NET.ftp.FTPClient;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.PropertySource;
- import org.springframework.stereotype.Component;
- import java.io.*;
- /**
- * @author Max
- */
- @Component
- @PropertySource("classpath:ftpResource.properties")
- public class FtpUtil {
- /**
- * FTP_ADDRESS: ftp 服务器 ip 地址
- * FTP_PORT: ftp 服务器 port, 默认是 21
- * FTP_USERNAME: ftp 服务器用户名
- * FTP_PASSWORD: ftp 服务器密码
- * FTP_BASE_PATH: ftp 服务器存储图片的绝对路径
- * IMAGE_BASE_URL: ftp 服务器外网访问图片路径
- */
- @Value("${FTP_ADDRESS}")
- private String FTP_ADDRESS;
- @Value("${FTP_PORT}")
- private Integer FTP_PORT;
- @Value("${FTP_USERNAME}")
- private String FTP_USERNAME;
- @Value("${FTP_PASSWORD}")
- private String FTP_PASSWORD;
- @Value("${FTP_BASE_PATH}")
- private String FTP_BASE_PATH;
- @Value("${IMAGE_BASE_URL}")
- private String IMAGE_BASE_URL;
- /**
- * 上传图片
- * @param inputStream 输入流
- * @param name 文件名
- * @return 图片 url
- * @throws IOException IO 异常
- */
- public String uploadImage(InputStream inputStream, String name) throws IOException {
- FTPClient ftpClient = new FTPClient();
- try {
- System.out.println(FTP_ADDRESS);
- ftpClient.enterLocalPassiveMode();
- ftpClient.connect(FTP_ADDRESS, FTP_PORT);
- ftpClient.login(FTP_USERNAME, FTP_PASSWORD);
- ftpClient.changeWorkingDirectory(FTP_BASE_PATH);
- ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
- boolean isSucceed = ftpClient.storeFile(name, inputStream);
- if (isSucceed){
- return IMAGE_BASE_URL + name;
- }
- }catch (Exception e){
- e.printStackTrace();
- }finally {
- ftpClient.logout();
- }
- return IMAGE_BASE_URL + "error";
- }
- }
然后在 Service 处理逻辑, 此处只展示部分代码
- @Autowired
- private FtpUtil ftpUtil;
- @Override
- public int insertImg(MultipartFile file) throws IOException {
- /*
- 1, 获取上传的文件流 inputStream 以及文件名 getOriginalFilename
- 2, 调用 FtpUtil 中的函数, 将图片上传到图片服务器并返回 https 地址
- 3, 若返回的是图片地址, 则将其插入数据库
- */
- InputStream inputStream = file.getInputStream();
- String filename = file.getOriginalFilename();
- String picUrl = ftpUtil.uploadImage(inputStream, filename);
- }
就这样完事儿, 以后客户端请求过来, 通过 FTP 传输到服务器, 然后将地址保存到数据库, 前端只要获取了图片 url 就会显示.
来源: https://www.cnblogs.com/lyuzt/p/12575390.html