小言_互联网的博客

基于SpringBoot+nginx实现资源上传

294人阅读  评论(0)

最近小编在学习使用nginx放置静态资源,例如图片、视频、css/js等,下面就来记录一下一波学习干货。

1.nginx安装及配置

小编使用的服务器是阿里云的轻量应用服务器,系统使用的是Ubuntu。注意记得开放 9090TCP端口,如果不使用 9090端口作为服务器端口也可不用。

安装

首先,获取安装包是必要的吧,这里提供一个nginx-1.11.3-ubuntu.tar.gz https://pan.baidu.com/s/1vvb41QkOJ4VqfyFckXBkjA (密码45wz)

小编是将安装包放在/usr/nginx 中,进入目录下然后执行 tar -zxvf nginx-1.11.3.tar.gz 进行解压

配置

修改 /usr/nginx/conf/nginx.conf :

server {
    listen      9090;
    server_name  localhost;

    location ~ .(jpg|png|jpeg|gif|bmp)$ {	#可识别的文件后缀
 		root /usr/nginx/image/;  	#图片的映射路径
        autoindex on;	#开启自动索引
 		expires 1h;		#过期时间
    }
	location ~ .(css|js)$ {
	    root /usr/nginx/static/;
        autoindex on;
	    expires 1h;
    } 
	location ~ .(AVI|mov|rmvb|rm|FLV|mp4|3GP)$ {
	    root /usr/nginx/video/;
        autoindex on;
	    expires 1h;
    }

该修改的修改,该增加的增加,切记勿乱删

最后一步,启动nginx,执行 ./usr/nginx/sbin/nginx

到这里服务器nginx就准备可以了
你可以试下在 /usr/nginx/image 下放图片01.jpg,然后在本地 http://ip:9090/01.jpg 看看图片能否访问到

2. SpringBoot 实现资源的上传

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>

appilcation.yml:

ftp:
  host: 自己服务器ip
  userName: 服务器账号
  password: 服务器密码
  port: 22
  rootPath: /usr/nginx/image
  img:
    url: http://ip:9090/      # ftp.img.url 可以不添加,这里只是为了上传文件成功后返回文件路径

工具类 FtpUtil.class:

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

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

@Component
public class FtpUtil {
    private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);

    /**
     * ftp服务器ip地址
     */
    private static String host;

    @Value("${ftp.host}")
    public void setHost(String val){
        FtpUtil.host = val;
    }

    /**
     * 端口
     */
    private static int port;

    @Value("${ftp.port}")
    public void setPort(int val){
        FtpUtil.port = val;
    }

    /**
     * 用户名
     */
    private static String userName;

    @Value("${ftp.userName}")
    public void setUserName(String val){
        FtpUtil.userName = val;
    }

    /**
     * 密码
     */
    private static String password;

    @Value("${ftp.password}")
    public void setPassword(String val){
        FtpUtil.password = val;
    }

    /**
     * 存放图片的根目录
     */
    private static String rootPath;

    @Value("${ftp.rootPath}")
    public void setRootPath(String val){
        FtpUtil.rootPath = val;
    }

    /**
     * 存放图片的路径
     */
    private static String imgUrl;

    @Value("${ftp.img.url}")
    public void setImgUrl(String val){
        FtpUtil.imgUrl = val;
    }

    /**
     * 获取连接
     */
    private static ChannelSftp getChannel() throws Exception{
        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上传图片
     * @param inputStream 图片io流
     * @param imagePath 路径,不存在就创建目录
     * @param imagesName 图片名称
     * @return urlStr 图片的存放路径
     */
    public static String putImages(InputStream inputStream, String imagePath, String imagesName){
        try {
            ChannelSftp sftp = getChannel();
            String path = rootPath + imagePath + "/";
            createDir(path,sftp);

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

            //处理返回的路径
            String resultFile;
            resultFile = imgUrl + imagePath + imagesName;

            return resultFile;

        } catch (Exception e) {
            logger.error("上传失败:" + e.getMessage());
        }
        return "";
    }

    /**
     * 创建目录
     */
    private static 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 );
                }
            }
        }
    }

    /**
     * 删除图片
     */
    public static void delImages(String imagesName){
        try {
            ChannelSftp sftp = getChannel();
            String path = rootPath + imagesName;
            sftp.rm(path);
            sftp.quit();
            sftp.exit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

工具类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神器一波


注意:
1.如果要视频跟图片一起上传的话,只要修改 nginx.conf配置文件,添加相应的视频后缀即可,代码没变,上传后也是放在 /usr/image 下,要不然文件能上传,但是访问不了
2.上面代码 uploads接口是实现多文件上传

源码下载
如果有什么需要改进的,还请多加指教。


转载:https://blog.csdn.net/qq_38752386/article/details/102453756
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场