【Docker+Nginx+SpringBoot】(實現頭像上傳功能)搭建一個圖片服務器,實現本地上傳圖片,並返回可以訪問的圖片鏈接。

參考
nginx+docker搭建靜態資源服務器
基於springboot搭建圖片服務器

問題的拋出

就拿CSDN來說,通常我們將本地的的照片託進去就會返回一個屬於這個圖片的鏈接,然而其他人可以通過這個鏈接訪問到我從本地拖進去的圖片。
在這裏插入圖片描述

經典案例

頭像的上傳,從本地上傳的圖片,那麼下次登錄也能訪問到。

Nginx+Docker 搭建靜態資源服務器

安裝docker

yum -y install docker

拉取nginx鏡像

docker pull nginx

準備工作

# 創建一個存放靜態資源的目錄,比如我是使用了 /home/ftpadmin/health/images( 建議不要使用 root 權限,不好使用 xftp 上傳文件 )
mkdir /home/ftpadmin/health/images
# 創建並編輯 nginx.conf,我的 nginx.conf 放在 /home/ftpadmin/health 路徑底下
vi nginx.conf

可以在Xftp下創建,最後可以看到是這樣的
在這裏插入圖片描述
修改nginx.conf

user  nginx;
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;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   /images;
            index  index.html index.htm;
        }
    }

    include /etc/nginx/conf.d/*.conf;
}

執行docker實例創建命令

# --name 實例名
# -p 是端口映射,80是 nginx 容器的默認端口,映射到主機的 4545 端口,也就是訪問宿主機的 4545  端口,就會自動跳轉到 nginx 容器的 80 端口,也就是 nginx 的入口
# -v 是掛載目錄,它會讓容器和宿主機共享目錄,我們把靜態資源放在 /home/ftpadmin/health/images,容器內的路徑 /images 也會更新靜態資源,記得改成自己的真實路徑
# 由於容器內沒有 vim 和 vi ,甚至沒有 yum ,所以我們無法在容器內修改,那麼可以選擇 將外部的 nginx 配置文件覆蓋容器內的配置文件

掛載命令

docker run --name images_nginx -p 4545:80 -v /home/ftpadmin/health/images:/images -v /home/ftpadmin/health/nginx.conf:/etc/nginx/nginx.conf -d nginx

可以用Xftp上傳幾個圖片
在這裏插入圖片描述
可以測試一下,圖片是否可以訪問啦

http://ip:4545/image.png

在這裏插入圖片描述

基於Springboot搭建圖片服務器

nginx已經準備完成啦,那麼現在我們要開始實現資源的上傳

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.7.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <!-- Apache工具組件 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.8.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>
        <version>3.6</version>
    </dependency>
    <!-- 文件上傳組件 -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.3</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.22</version>
    </dependency>
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.54</version>
    </dependency>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.10.3</version>
    </dependency>
</dependencies>

application.yml

ftp:
  host: 自己服務器ip
  userName: 服務器賬號
  password: 服務器密碼
  port: 22
  rootPath: /usr/nginx/image
  img:
    url: http://ip:4545     # ftp.img.url 可以不添加,這裏只是爲了上傳文件成功後返回文件路徑

工具類 FtpUtil.class


import com.fehead.community.error.BusinessException;
import com.fehead.community.error.EmBusinessError;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


import java.io.InputStream;
import java.util.Properties;

@Component
@Slf4j
public class FtpUtil {

    //ftp服務器ip地址
    @Value("${ftp.host}")
    private String host;
    //端口
    @Value("${ftp.port}")
    private Integer port;
    //用戶名
    @Value("${ftp.userName}")
    private String userName;
    //密碼
    @Value("${ftp.password}")
    private String password;
    //存放圖片的根目錄
    @Value("${ftp.rootPath}")
    private String rootPath;
    //存放圖片的路徑
    @Value("${ftp.img.url}")
    private String imgUrl;
    //獲取鏈接
    private ChannelSftp getChannel() throws JSchException {
        JSch jSch=new JSch();
        //->ssh root@host:port
        Session sshSession=jSch.getSession(userName,host,port);
        //密碼
        sshSession.setPassword(password);

        Properties sshConfig=new Properties();
        sshConfig.put("StrictHostKeyChecking", "no");
        sshSession.setConfig(sshConfig);
        sshSession.connect();

        Channel channel=sshSession.openChannel("sftp");
        channel.connect();

        return (ChannelSftp) channel;
    }

    //ftp上傳圖片
    public String putImages(InputStream inputStream,String imagePath,String imagesName) throws JSchException, SftpException, BusinessException {
        try {
            ChannelSftp sftp = getChannel();
            String path = rootPath + imagePath + "/";
            //創建目錄
            createDir(path, sftp);

            //上傳文件
            sftp.put(inputStream, path + imagesName);
            log.info("上傳成功!");
            sftp.quit();
            sftp.exit();

            //處理返回的路徑
            String resultFile;
            resultFile = imgUrl + imagePath + imagesName;
            return resultFile;
        }catch (Exception e){
            log.info("上傳失敗");
            throw new BusinessException(EmBusinessError.IMAGE_INSERT_ERROR);
        }
    }

    //創建目錄
    private void createDir(String path,ChannelSftp sftp) throws SftpException {
        String[] folders=path.split("/");
        sftp.cd("/");
        for(String folder:folders){
            if(folder.length()>0){
                try{
                    sftp.cd(folder);
                }catch (SftpException e){
                    sftp.mkdir(folder);
                    sftp.cd(folder);
                }
            }
        }

    }
}

工具類IDUtils.class(修改上傳圖片名)

import java.util.Random;

public class IDUtils {

    /**
     * 生成隨機圖片名
     */
    public static String genImageName() {
        //取當前時間的長整形值包含毫秒
        long millis = System.currentTimeMillis();
        //加上三位隨機數
        Random random = new Random();
        int end3 = random.nextInt(999);
        //如果不足三位前面補0
        String str = millis + String.format("%03d", end3);
        
        return str;
    }

}

NginxService.class

import com.wzy.util.FtpUtil;
import com.wzy.util.IDUtils;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * @Package: com.wzy.service
 * @Author: Clarence1
 * @Date: 2019/10/4 21:34
 */
@Service
@Slf4j
public class NginxService {

    public Object uploadPicture(MultipartFile uploadFile) {
        //1、給上傳的圖片生成新的文件名
        //1.1獲取原始文件名
        String oldName = uploadFile.getOriginalFilename();
        //1.2使用IDUtils工具類生成新的文件名,新文件名 = newName + 文件後綴
        String newName = IDUtils.genImageName();
        assert oldName != null;
        newName = newName + oldName.substring(oldName.lastIndexOf("."));
        //1.3生成文件在服務器端存儲的子目錄
        String filePath = new DateTime().toString("/yyyyMMdd/");

        //2、把圖片上傳到圖片服務器
        //2.1獲取上傳的io流
        InputStream input = null;
        try {
            input = uploadFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //2.2調用FtpUtil工具類進行上傳
        return FtpUtil.putImages(input, filePath, newName);
    }

}

NginxController.class

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wzy.service.NginxService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;

@RestController
@Slf4j
public class NginxController {

    @Autowired
    private NginxService nginxService;

    /**
     * 可上傳圖片、視頻,只需在nginx配置中配置可識別的後綴
     */
    @PostMapping("/upload")
    public String pictureUpload(@RequestParam(value = "file") MultipartFile uploadFile) {
        long begin = System.currentTimeMillis();
        String json = "";
        try {
            Object result = nginxService.uploadPicture(uploadFile);
            json = new ObjectMapper().writeValueAsString(result);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        log.info("任務結束,共耗時:[" + (end-begin) + "]毫秒");
        return json;
    }

    @PostMapping("/uploads")
    public Object picturesUpload(@RequestParam(value = "file") MultipartFile[] uploadFile) {
        long begin = System.currentTimeMillis();
        Map<Object, Object> map = new HashMap<>(10);

        int count = 0;
        for (MultipartFile file : uploadFile) {
            Object result = nginxService.uploadPicture(file);
            map.put(count, result);
            count++;
        }
        long end = System.currentTimeMillis();
        log.info("任務結束,共耗時:[" + (end-begin) + "]毫秒");
        return map;
    }

}


PostMan測試

在這裏插入圖片描述
然後複製下方鏈接,就可以訪問啦
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章