docker部署springboot项目文件上传路径过程
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、问题</a></li><li><a href="#_label1">二、环境</a></li><li><a href="#_label2">三、创建springboot项目</a></li><li><a href="#_label3">四、docker部署项目</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_0">(1)构建镜像</a></li><li><a href="#_lab2_3_1">(2)启动容器</a></li><ul class="third_class_ul"><li><a href="#_label3_3_1_0">(1)不挂载文件启动容器</a></li><li><a href="#_label3_3_1_1">(2)挂载文件启动容器</a></li></ul></ul><li><a href="#_label4">三、补充</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">四、总结</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、问题</h2><p>解决通过docker部署springboot项目,文件上传的路径该怎么设置?</p>
<p>用docker部署后,在服务器上面怎么看到自己上传的文件,文件需不需要挂载等问题,下面直接使用springboot+docker简单搭建一个文件服务器</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、环境</h2>
<p>以下是本人此次搭建的环境</p>
<ul><li>部署方式:docker</li><li>服务器:linux服务器</li><li>服务器操作系统:CentOS 8.2</li><li>jdk:1.8</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>三、创建springboot项目</h2>
<p>创建springboot项目upload-demo,先在本地进行测试,确保本地的项目可以进行文件上传和下载</p>
<p><strong>pom</strong></p>
<div class="jb51code"><pre class="brush:xml;"><?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zqcn</groupId>
<artifactId>upload_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>upload_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
</pre></div>
<p>application.yml</p>
<div class="jb51code"><pre class="brush:yaml;">upload:
#部署服务器时的服务上文件存放地址
#path: /upload-demo/upload
# 本地的文件存放地址
path: D:\zqcn\data\upload-demo\upload
server:
port: 8082
</pre></div>
<p>为了方便直观的看到效果,这里就简单写了两个html页面进行测试</p>
<p><strong>upload-page.html(文件上传页面)</strong></p>
<div class="jb51code"><pre class="brush:xhtml;"><!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form enctype="multipart/form-data" method="post" action="/file/receive">
<div>
File Choose:
<input type="file" name="file"></div>
<div>
<input type="submit" value="Submit"/>
</div>
</form>
</body>
</html>
</pre></div>
<p><strong>download-page.html(文件下载页面)</strong></p>
<div class="jb51code"><pre class="brush:xhtml;"><!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<form action="/file/fetch" method="post">
下载文件名:<input type="text" name="fileName" maxlength="500" style="width:400px;">
<input type="submit" value="提交">
</form>
</body>
</html>
</pre></div>
<p>最后编写对应的controller即可</p>
<p><strong>FileController</strong></p>
<div class="jb51code"><pre class="brush:bash;">package com.zqcn.upload_demo.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName : FileController
* @Description :
* @Author : CJH
* @Date: 2022-06-15 09:37
*/
@Controller
@RequestMapping("/file")
public class FileController {
@Value("${upload.path}")
private String uploadPath;
/**
* 文件上传页面
* @param request
* @return
*/
@RequestMapping("/upload")
public String uploadPage(HttpServletRequest request){
return "upload-page";
}
/**
* 文件下载页面
* @param request
* @return
*/
@RequestMapping("/download")
public String downloadPage(HttpServletRequest request){
return "download-page";
}
/**
* 文件上传接口
* @param file
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value="/receive", method = RequestMethod.POST)
public Map receiveFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception{
if(file.isEmpty()){
return new HashMap<String,Object>(){{
put("code",500);
put("msg","没有选中任何文件");
put("status",false);
put("data",null);
}};
}
File uploadFileSaveDir = new File(uploadPath);
System.out.println("上传文件的存放目录:"+uploadFileSaveDir.getAbsolutePath());
if(!uploadFileSaveDir.exists()){
// 递归生成文件夹
uploadFileSaveDir.mkdirs();
}
// 拿到文件名
String filename = file.getOriginalFilename();
// 构建真实的文件路径
File uploadFile = new File(uploadFileSaveDir.getAbsolutePath() + File.separator + filename);
System.out.println("文件上传到:" + uploadFile.getAbsolutePath());
//文件写到服务器,
file.transferTo(uploadFile);
return new HashMap<String,Object>(){{
put("code",200);
put("msg","文件上传成功");
put("status",true);
put("data",null);
}};
}
/**
* 文件下载接口
* @param fileName
* @param response
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = "/fetch", method = RequestMethod.POST)
public Map fileDownload(@RequestParam() String fileName, HttpServletResponse response)throws Exception{
File downloadFile = new File(uploadPath + File.separator + fileName);
System.out.println("下载文件的完整路径:"+downloadFile.getAbsolutePath());
if(!downloadFile.exists()){
System.out.println("要下载的文件不存在:"+downloadFile.getAbsolutePath());
return new HashMap<String,Object>(){{
put("code",500);
put("msg","文件不存在,下载失败");
put("status",false);
put("data",null);
}};
}else {
//第二读取文件
InputStream in = new FileInputStream(downloadFile);
//设置响应头,对文件进行url编码
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
response.setContentLength(in.available());
//第三步:读文件写入http响应
OutputStream out = response.getOutputStream();
byte[] b = new byte;
int len = 0;
while((len = in.read(b))!=-1){
out.write(b, 0, len);
}
out.flush();
out.close();
in.close();
return new HashMap<String,Object>(){{
put("code",200);
put("msg","文件下载成功");
put("status",true);
put("data",null);
}};
}
}
}
</pre></div>
<p>启动项目,先用postman测试一下上传接口</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502481.png" /></p>
<p>再测试一下下载接口</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502568.png" /></p>
<p>接口测试没问题,下面可以测一下那两个页面</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502431.png" /></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502566.png" /></p>
<p>都是正常的,本地项目创建成功</p>
<p class="maodian"><a name="_label3"></a></p><h2>四、docker部署项目</h2>
<p class="maodian"><a name="_lab2_3_0"></a></p><h3>(1)构建镜像</h3>
<p>关于linux服务器和docker的基础知识这里就不赘述了,自行百度即可,下面直接进入部署流程,先把项目的文件上传路径改成部署环境的上传地址</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502573.png" /></p>
<p>再本地进行jar打包</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502534.png" /></p>
<p>创建Dockerfile文件</p>
<div class="jb51code"><pre class="brush:bash;">FROMjava
VOLUME/tmp
ADD upload_demo.jar upload_demo.jar
EXPOSE 8082
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/upload_demo.jar"]
</pre></div>
<ul><li>FROM java:表示安装的java镜像</li><li>VOLUME /tmp:创建/tmp目录并持久化到Docker数据文件夹</li><li>ADD upload_demo.jar upload_demo.jar:将生成的jar包(第一个)复制并重命名到upload_demo.jar(第二个)</li><li>EXPOSE 8082:对外暴露的接口,也是访问的接口,接口的端口号需要根据springboot项目配置的端口号来设置</li><li>ENTRYPOINT:固定写法,用来运行jar包,相当于java -jar xxx.jar一样</li></ul>
<p>最后将jar和Dockerfile通过xftp一起上传到服务器上面,最好找个文件夹统一放在一起,例如</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502569.png" /></p>
<p>再通过xshell进入jar和Dockerfile所在的目录,并且输入构建镜像的命令</p>
<div class="jb51code"><pre class="brush:bash;">docker build -t upload-demo .
</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502571.png" /></p>
<p>构建成功后,先随便创建</p>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>(2)启动容器</h3>
<p>为了更清楚的理解docker部署的项目文件上传路径,这里分两种方式启动容器,一种不挂载文件,一种挂载文件,两种方式,简单分析一下文件的上传路径</p>
<p class="maodian"><a name="_label3_3_1_0"></a></p><h4>(1)不挂载文件启动容器</h4>
<p>命令如下:</p>
<div class="jb51code"><pre class="brush:bash;">sudo docker run -d --name upload-demo01 -p 8082:8082upload-demo
</pre></div>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502566.png" /></p>
<p>容器启动成功后,用postman进行文件上传测试,上传了1.jpeg文件</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502557.png" /></p>
<p>上传也是成功了,那么怎么看到上传的图片呢,还有就springboot项目配置的文件上传地址体现在哪里,要想知道这些答案,就需要进入容器内部看了,命令</p>
<div class="jb51code"><pre class="brush:bash;">docker exec -it upload-demo01 /bin/bash
</pre></div>
<p>进入里面后查看当前目录下的文件,就会发现upload-demo,这个就springboot配置的上传地址</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502513.png" /></p>
<p>再进入upload-demo文件里面看看</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502593.png" /></p>
<p>就会发现里面有一个文件夹upload,再深入里面看看,就会发现里面有一张图片1.jpeg,就是我们上传的图片了</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502561.png" /></p>
<p>总结一下容器里面的路径地址就是:/upload-demo/upload,这个路径就是springboot配置的文件上传地址</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502583.png" /></p>
<p>至此为止,整体容器启动后,文件上传和下载都是正常的,唯一不足的就是,如果要看这个图片上传在哪里,就需要进入容器里面看,下面推荐第二种方式,启动容器后,并且把容器里面的图片挂载出来</p>
<p class="maodian"><a name="_label3_3_1_1"></a></p><h4>(2)挂载文件启动容器</h4>
<p>先在服务器上创建一个目录,用于存放挂载出来的图片,本人的路径是/home/cainiao/upload-demo/upload</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502556.png" /></p>
<p>下面执行以下命令启动容器:</p>
<div class="jb51code"><pre class="brush:bash;"> sudo docker run -d --name upload-demo02 -p 8083:8082-v /home/cainiao/upload-demo/upload:/upload-demo/upload upload-demo
</pre></div>
<p>注意:</p>
<ul><li>/home/cainiao/upload-demo/upload:是你要挂载到容器外面的服务器图片路径</li><li>/upload-demo/upload:是容器里面图片地址</li></ul>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502548.png" /></p>
<p>容器启动成功,现在用postman进行接口上传测试,文件2.jpeg上传成功</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502578.png" /></p>
<p>现在去服务器上面的/home/cainiao/upload-demo/upload里面,刷新一下,看一下发现图片已经挂载出来了</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502521.png" /></p>
<p>现在试一下图片下载</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010609502597.jpg" /></p>
<p>可以看到图片,经过测试,图片可以完成下载</p>
<p class="maodian"><a name="_label4"></a></p><h2>三、补充</h2>
<p>正常部署的话,建议采用第二种采用挂载文件的形式进行启动</p>
<p class="maodian"><a name="_label5"></a></p><h2>四、总结</h2>
<p>以上为个人经验,希望能给大家一个参考,也希望大家多多支持琼殿技术社区。</p>
頁:
[1]