最近在学nginx,然后想起了之前大学做的一个商城网站,图片就是用nginx作为图片服务器,在这里分享记录一下。
技术:Nginx,Vsftpd,Spring,SpringMVC,KindEditor,CentOS,注意KindEditor这个富文本编辑器他不是事先图片服务器的必要技术,只是使用 KindEditer 是为了更好的演示图片的上传,回显,批量效果。后台代码与KindEditer没有直接关系。
一、介绍
场景:用户将图片上传到 tomcat 服务器上,再由 tomcat 服务器通过FTP上传到 Nginx 服务器上。
项目结构:
二、代码介绍
首先要攻破核心技术。通过单元测试实现图片上传的功能。
public class PictureFTPTest {
// 测试 ftp 上传图片功能
@Test
public void testFtpClient() throws Exception {
// 1. 创建一个FtpClient对象
FTPClient ftpClient = new FTPClient();
// 2. 创建 ftp 连接
ftpClient.connect("192.168.0.11", 21);
// 3. 登录 ftp 服务器
ftpClient.login("ftpuser", "root");
// 4. 读取本地文件
FileInputStream inputStream = new FileInputStream(new File("F:\\hello.png"));
// 5. 设置上传的路径
ftpClient.changeWorkingDirectory("/usr/local/nginx/html/images");
// 6. 修改上传文件的格式为二进制
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// 7. 服务器存储文件,第一个参数是存储在服务器的文件名,第二个参数是文件流
ftpClient.storeFile("hello.jpg", inputStream);
// 8. 关闭连接
ftpClient.logout();
}
}
说明:这里的ip地址,端口,ftp用户名,密码,本地文件路径,以及Nginx服务器图片路径等,这些字符串参数都要根据自己实际设置的来填写的。如果你的Nginx和Vsftpd安装是按照我提供的链接来做的。那你只需要改ip地址即可。
三、Maven 的Web 项目
项目核心配置文件:首先是 Maven 的核心文件 pom.xml,添加下列对应版本的依赖即可,可前去https://mvnrepository.com/tags/maven 查找依赖。
<!--定义别名-->
<properties>
<java-version>1.8</java-version>
<servlet-version>3.1.0</servlet-version>
<junit-version>4.12</junit-version>
<springframework-version>4.2.6.RELEASE</springframework-version>
<mybatis-version>3.4.1</mybatis-version>
<mybatis-spring-version>1.3.0</mybatis-spring-version>
<mysql-version>5.1.38</mysql-version>
<hibernate-validator-version>5.4.1.Final</hibernate-validator-version>
<druid-version>1.0.28</druid-version>
<commons-lang-version>2.6</commons-lang-version>
<commons-fileupload-version>1.3.1</commons-fileupload-version>
<commons-io-version>2.5</commons-io-version>
<commons-codec-version>1.10</commons-codec-version>
<commons-configuration-version>1.10</commons-configuration-version>
<slf4j-version>1.7.19</slf4j-version>
<log4j-version>1.2.17</log4j-version>
<fastjson-version>1.2.30</fastjson-version>
<shiro-version>1.3.2</shiro-version>
<kaptcha-version>0.0.9</kaptcha-version>
<velocity-version>1.7</velocity-version>
<velocity-tools-version>2.0</velocity-tools-version>
<jstl-version>1.2</jstl-version>
<taglibs-version>1.1.2</taglibs-version>
<freemarker-version>2.3.23</freemarker-version>
<poi.version>3.15</poi.version>
<sub.version>3.1.0</sub.version>
</properties>
说明:和文件上传有直接关系的是:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
然后是 Web 项目的核心文件 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="taotao" version="2.5">
<display-name>pictrue-service</display-name>
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>pictrue-service</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>pictrue-service</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
再是 SpringMVC 配置文件 springmvc.xml,需要添加文件上传解析器
<!-- 定义文件上传解析器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5242880"></property>
</bean>
最后是 Ftp 配置文件 resource.properties
#ftp图片服务器连接参数
#FTP_HOST=192.168.23.130
FTP_HOST=192.168.175.128
FTP_PROT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=199507
FTP_BASEURL=/home/ftpuser/mqc/image
##图片回显路径
PICTURE_BASEURL=http://192.168.175.128/image/
#PICTURE_BASEURL=http://192.168.23.130/image/
Service 层
package com.mqc.service.upload;
import com.mqc.common.result.PictureResult;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* @author 毛其传
* @Description: 图片上传服务逻辑接口
* @date 2018/4/11
*/
public interface IPictureService {
/**
* @Description: 上传图片到Nginx服务器
* @author 毛其传
* @date 2018/4/11
*/
PictureResult uploadPicture(MultipartFile file);
}
上传图片接口实现类 PictureServiceImpl.java
package com.mqc.service.upload.impl;
import com.mqc.common.constant.PictureConstant;
import com.mqc.common.result.PictureResult;
import com.mqc.service.upload.IPictureService;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* @author 毛其传
* @Description: 图片上传服务逻辑实现类
* @date 2018/4/11
*/
@Service
public class PictureServiceImpl implements IPictureService {
@Value("${FTP_HOST}")
private String FTP_HOST; //Nginx服务器地址
@Value("${FTP_USERNAME}")
private String FTP_USER; //ftp用户名
@Value("${FTP_PASSWORD}")
private String FTP_PASSWORD; //ftp密码
@Value("${FTP_BASEURL}")
private String PICTURE_BASE_URL; //图片上传的基础路径
@Value("${PICTURE_BASEURL}")
private String PICTURE_URL; //图片回调的基础路径
/**
* @Description: 上传图片到Nginx服务器
* @author 毛其传
* @date 2018/4/11
*/
@Override
public PictureResult uploadPicture(MultipartFile file) {
PictureResult result = new PictureResult();
try {
if (null != file) {
//图片原始名称
String filename = file.getOriginalFilename();
//图片的类型
String fileType = filename.substring(filename.indexOf("."));
//上传之后图片的名称
String new_fileName = PictureConstant.genImageName() + fileType;
FTPClient client = new FTPClient();
client.connect(FTP_HOST);
client.login(FTP_USER, FTP_PASSWORD);
client.changeWorkingDirectory(PICTURE_BASE_URL);
//解决上传0字节问题
client.enterLocalPassiveMode();
//设置图片上传格式为二进制
client.setFileType(FTP.BINARY_FILE_TYPE);
client.storeFile(new_fileName, file.getInputStream());
client.logout();
//图片上传成功
result.setError(0);
result.setUrl(PICTURE_URL + new_fileName);
} else {
result.setError(1);
result.setMessage("上传图片不能为空");
}
} catch (Exception e) {
e.printStackTrace();
result.setError(1);
result.setMessage("上传失败");
}
return result;
}
}
Controller 层:负责页面跳转的 PageController.java
@Controller
public class PageController {
/**
* 打开首页
*/
@RequestMapping("/")
public String showIndex() {
return "index";
}
@RequestMapping("/{page}")
public String showpage(@PathVariable String page) {
System.out.println("page : " + page);
return page;
}
}
负责图片上传的 PictureController.java
@RestController
public class PictureController {
@Autowired
private PictureService pictureService;
@RequestMapping("pic/upload")
public String pictureUpload(@RequestParam(value = "fileUpload") MultipartFile uploadFile) {
String json = "";
try {
Map result = pictureService.uploadPicture(uploadFile);
// 浏览器擅长处理json格式的字符串,为了减少因为浏览器内核不同导致的bug,建议用json
json = new ObjectMapper().writeValueAsString(result);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
}
}
Views视图层
<form action="pic/upload" method="post" enctype="multipart/form-data">
<input type="file" name="fileUpload" />
<input type="submit" value="上传文件" />
</form>
<hr />
<h3>借用KindEditor富文本编辑器实现批量上传图片</h3>
<textarea id="kindEditorDesc" style="width:800px;height:300px;visibility:hidden;"></textarea>
<script type="text/javascript">
$(function(){
//初始化富文本编辑器
KindEditor.create("#kindEditorDesc", {
// name值,必须和Controller 的参数对应,不然会提示 400 的错误
filePostName : "fileUpload",
// action值,
uploadJson : '/pic/upload',
// 设置上传类型,分别为image、flash、media、file
dir : "image"
});
});
</script>
说明:视图分为两个部分,第一个部分是为了测试上传图片功能的form表单。第二个部分是为了更好的体验上传,批量上传,回显功能的KindEditer 富文本编辑器。
总结
-
Nginx 搭建服务器的思维
-
Java实现 Ftp上传图片的功能
-
KindEditer 上传图片的功能
Nginx 搭建图片服务器到这里就结束了,有什么不足的地方,请赐教。如果觉得不错,可以点个赞哦!