Nginx 搭建图片服务器
本章內(nèi)容通過(guò)Nginx 和 FTP 搭建圖片服務(wù)器。在學(xué)習(xí)本章內(nèi)容前,請(qǐng)確保您的Linux 系統(tǒng)已經(jīng)安裝了Nginx和Vsftpd。
Nginx 安裝
http://www.cnblogs.com/itdragon/p/7850985.html
Vsftpd 安裝
http://www.cnblogs.com/itdragon/p/7857649.html
本章知識(shí)點(diǎn)
效果圖:
-
需求:實(shí)現(xiàn)圖片的上傳和批量上傳
-
技術(shù):Nginx,Vsftpd,Spring,SpringMVC,KindEditor,CentOS
-
說(shuō)明:本章節(jié)內(nèi)容主要是實(shí)現(xiàn)圖片的上傳功能。使用 KindEditer 是為了更好的演示圖片的上傳,回顯,批量效果。后臺(tái)代碼與KindEditer沒(méi)有直接關(guān)系,放心閱讀。另外源碼中有Mybatis的jar,不用理會(huì),本章內(nèi)容用不到,是為后續(xù)內(nèi)容做準(zhǔn)備!
-
源碼:見(jiàn)文章底部
-
場(chǎng)景:用戶將圖片上傳到 tomcat 服務(wù)器上,再由 tomcat 服務(wù)器通過(guò)FTP上傳到 Nginx 服務(wù)器上。
項(xiàng)目結(jié)構(gòu):
單元測(cè)試
首先要攻破核心技術(shù)。通過(guò)單元測(cè)試實(shí)現(xiàn)圖片上傳的功能。
package?com.itdragon.test;import?java.io.File; import?java.io.FileInputStream;import?org.apache.commons.net.ftp.FTP; import?org.apache.commons.net.ftp.FTPClient; import?org.junit.Test;public?class?PictureFTPTest?{//?測(cè)試?ftp?上傳圖片功能@Testpublic?void?testFtpClient()?throws?Exception?{//?1.?創(chuàng)建一個(gè)FtpClient對(duì)象FTPClient?ftpClient?=?new?FTPClient();//?2.?創(chuàng)建?ftp?連接ftpClient.connect("192.168.0.11",?21);//?3.?登錄?ftp?服務(wù)器ftpClient.login("ftpuser",?"root");//?4.?讀取本地文件FileInputStream?inputStream?=?new?FileInputStream(new?File("F:\\hello.png"));//?5.?設(shè)置上傳的路徑ftpClient.changeWorkingDirectory("/usr/local/nginx/html/images");//?6.?修改上傳文件的格式為二進(jìn)制ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//?7.?服務(wù)器存儲(chǔ)文件,第一個(gè)參數(shù)是存儲(chǔ)在服務(wù)器的文件名,第二個(gè)參數(shù)是文件流ftpClient.storeFile("hello.jpg",?inputStream);//?8.?關(guān)閉連接ftpClient.logout();}}說(shuō)明:這里的ip地址,端口,ftp用戶名,密碼,本地文件路徑,以及Nginx服務(wù)器圖片路徑等,這些字符串參數(shù)都要根據(jù)自己實(shí)際設(shè)置的來(lái)填寫(xiě)的。如果你的Nginx和Vsftpd安裝是按照我提供的鏈接來(lái)做的。那你只需要改ip地址即可。
Maven 的Web 項(xiàng)目
搭建Maven的Web 項(xiàng)目,之前有寫(xiě)過(guò)。這里就不過(guò)多描述。
項(xiàng)目核心配置文件
首先是 Maven 的核心文件 pom.xml
<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?http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itdragon.upload</groupId><artifactId>pictrue-service</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><!--?集中定義依賴版本號(hào)?--><properties><junit.version>4.12</junit.version><spring.version>4.1.3.RELEASE</spring.version><mybatis.version>3.2.8</mybatis.version><mybatis.spring.version>1.2.2</mybatis.spring.version><mybatis.paginator.version>1.2.15</mybatis.paginator.version><mysql.version>5.1.6</mysql.version><slf4j.version>1.6.4</slf4j.version><jackson.version>2.4.2</jackson.version><druid.version>1.0.9</druid.version><httpclient.version>4.3.5</httpclient.version><jstl.version>1.2</jstl.version><servlet-api.version>2.5</servlet-api.version><jsp-api.version>2.0</jsp-api.version><joda-time.version>2.5</joda-time.version><commons-lang3.version>3.3.2</commons-lang3.version><commons-io.version>1.3.2</commons-io.version><commons-net.version>3.3</commons-net.version><pagehelper.version>3.4.2</pagehelper.version><jsqlparser.version>0.9.1</jsqlparser.version><commons-fileupload.version>1.3.1</commons-fileupload.version><jedis.version>2.7.2</jedis.version><solrj.version>4.10.3</solrj.version></properties><dependencies><!--?時(shí)間操作組件?--><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId><version>${joda-time.version}</version></dependency><!--?Apache工具組件?--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>${commons-lang3.version}</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>${commons-io.version}</version></dependency><dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>${commons-net.version}</version></dependency><!--?Jackson?Json處理工具包?--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency><!--?httpclient?--><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>${httpclient.version}</version></dependency><!--?單元測(cè)試?--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><!--?日志處理?--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><!--?Mybatis?--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis.spring.version}</version></dependency><dependency><groupId>com.github.miemiedev</groupId><artifactId>mybatis-paginator</artifactId><version>${mybatis.paginator.version}</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>${pagehelper.version}</version></dependency><!--?MySql?--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!--?連接池?--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!--?Spring?--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><!--?JSP相關(guān)?--><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>${jstl.version}</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>${servlet-api.version}</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><version>${jsp-api.version}</version><scope>provided</scope></dependency><!--?文件上傳組件?--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>${commons-fileupload.version}</version></dependency><!--?Redis客戶端?--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>${jedis.version}</version></dependency><!--?solr客戶端?--><dependency><groupId>org.apache.solr</groupId><artifactId>solr-solrj</artifactId><version>${solrj.version}</version></dependency></dependencies><build><finalName>${project.artifactId}</finalName><plugins><!--?資源文件拷貝插件?--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.7</version><configuration><encoding>UTF-8</encoding></configuration></plugin><!--?java編譯插件?--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.2</version><configuration><source>1.7</source><target>1.7</target><encoding>UTF-8</encoding></configuration></plugin></plugins><pluginManagement><plugins><!--?配置Tomcat插件?--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version></plugin></plugins></pluginManagement></build> </project>說(shuō)明:和文件上傳有直接關(guān)系的是:
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId> </dependency>然后是 Web 項(xiàng)目的核心文件 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"><!--?設(shè)定默認(rèn)編碼?--><property?name="defaultEncoding"?value="UTF-8"></property><!--?設(shè)定文件上傳的最大值5MB,5*1024*1024?--><property?name="maxUploadSize"?value="5242880"></property></bean>最后是 Ftp 配置文件 resource.properties
FTP_ADDRESS=192.168.0.11 FTP_PORT=21 FTP_USERNAME=ftpuser FTP_PASSWORD=root FTP_BASE_PATH=/usr/local/nginx/html/images IMAGE_BASE_URL=http://192.168.0.11/imagesService 層
上傳圖片的接口 PictureService.java
package?com.itdragon.service; import?java.util.Map; import?org.springframework.web.multipart.MultipartFile; public?interface?PictureService?{/***?上傳,批量上傳接口*?@param?uploadFile*?@return*/Map?uploadPicture(MultipartFile?uploadFile); }上傳圖片接口實(shí)現(xiàn)類 PictureServiceImpl.java
package?com.itdragon.service.impl;import?java.io.IOException; import?java.io.InputStream; import?java.util.HashMap; import?java.util.Map;import?org.apache.commons.net.ftp.FTP; import?org.apache.commons.net.ftp.FTPClient; import?org.apache.commons.net.ftp.FTPReply; import?org.springframework.beans.factory.annotation.Value; import?org.springframework.stereotype.Service; import?org.springframework.web.multipart.MultipartFile;import?com.itdragon.service.PictureService;@Service @SuppressWarnings({"rawtypes",?"unchecked"}) public?class?PictureServiceImpl?implements?PictureService?{//?通過(guò)?Spring4?的?Value注解,獲取配置文件中的屬性值@Value("${FTP_ADDRESS}")private?String?FTP_ADDRESS;?????//?ftp?服務(wù)器ip地址@Value("${FTP_PORT}")private?Integer?FTP_PORT;???????//?ftp?服務(wù)器port,默認(rèn)是21@Value("${FTP_USERNAME}")private?String?FTP_USERNAME;????//?ftp?服務(wù)器用戶名@Value("${FTP_PASSWORD}")private?String?FTP_PASSWORD;????//?ftp?服務(wù)器密碼@Value("${FTP_BASE_PATH}")private?String?FTP_BASE_PATH;???//?ftp?服務(wù)器存儲(chǔ)圖片的絕對(duì)路徑@Value("${IMAGE_BASE_URL}")private?String?IMAGE_BASE_URL;??//?ftp?服務(wù)器外網(wǎng)訪問(wèn)圖片路徑@Overridepublic?Map?uploadPicture(MultipartFile?uploadFile)?{Map?resultMap?=?new?HashMap<>();try?{//?1.?取原始文件名String?oldName?=?uploadFile.getOriginalFilename();//?2.?ftp?服務(wù)器的文件名String?newName?=?oldName;//圖片上傳boolean?result?=?uploadFile(FTP_ADDRESS,?FTP_PORT,?FTP_USERNAME,?FTP_PASSWORD,?uploadFile.getInputStream(),?FTP_BASE_PATH,?newName);//返回結(jié)果if(!result)?{resultMap.put("error",?1);resultMap.put("message",?"upload?Fail");return?resultMap;}resultMap.put("error",?0);resultMap.put("url",?IMAGE_BASE_URL?+?"/"?+?newName);return?resultMap;}?catch?(Exception?e)?{e.printStackTrace();resultMap.put("error",?1);resultMap.put("message",?"upload?Fail");return?resultMap;}}/***?ftp?上傳圖片方法*?@param?ip????????????ftp?服務(wù)器ip地址*?@param?port??????????ftp?服務(wù)器port,默認(rèn)是21*?@param?account???????ftp?服務(wù)器用戶名*?@param?passwd????????ftp?服務(wù)器密碼*?@param?inputStream???文件流*?@param?workingDir????ftp?服務(wù)器存儲(chǔ)圖片的絕對(duì)路徑*?@param?fileName??????上傳到ftp?服務(wù)器文件名*?@throws?Exception*?*/public?boolean?uploadFile(String?ip,?Integer?port,?String?account,?String?passwd,InputStream?inputStream,?String?workingDir,?String?fileName)?throws?Exception{boolean?result?=?false;//?1.?創(chuàng)建一個(gè)FtpClient對(duì)象FTPClient?ftpClient?=?new?FTPClient();try?{//?2.?創(chuàng)建?ftp?連接ftpClient.connect(ip,?port);//?3.?登錄?ftp?服務(wù)器ftpClient.login(account,?passwd);int?reply?=?ftpClient.getReplyCode();?//?獲取連接ftp?狀態(tài)返回值System.out.println("code?:?"?+?reply);if?(!FTPReply.isPositiveCompletion(reply))?{ftpClient.disconnect();?//?如果返回狀態(tài)不再?200?~?300?則認(rèn)為連接失敗return?result;}//?4.?讀取本地文件 //??????????FileInputStream?inputStream?=?new?FileInputStream(new?File("F:\\hello.png"));//?5.?設(shè)置上傳的路徑ftpClient.changeWorkingDirectory(workingDir);//?6.?修改上傳文件的格式為二進(jìn)制ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//?7.?服務(wù)器存儲(chǔ)文件,第一個(gè)參數(shù)是存儲(chǔ)在服務(wù)器的文件名,第二個(gè)參數(shù)是文件流if?(!ftpClient.storeFile(fileName,?inputStream))?{return?result;}//?8.?關(guān)閉連接inputStream.close();ftpClient.logout();result?=?true;}?catch?(Exception?e)?{e.printStackTrace();}finally?{//?FIXME?聽(tīng)說(shuō),項(xiàng)目里面最好少用try?catch?捕獲異常,這樣會(huì)導(dǎo)致Spring的事務(wù)回滾出問(wèn)題???難道之前寫(xiě)的代碼都是假代碼!!!if?(ftpClient.isConnected())?{try?{ftpClient.disconnect();}?catch?(IOException?ioe)?{}}}return?result;}}說(shuō)明:
-
@Value 注解是Spring4 中提供的,@Value("${XXX}")
-
返回值是一個(gè)Map,并且key有error,url,message。這是根據(jù)KindEditer的語(yǔ)法要求來(lái)的。詳情見(jiàn)鏈接。http://kindeditor.net/docs/upload.html
Controller 層
負(fù)責(zé)頁(yè)面跳轉(zhuǎn)的 PageController.java
package?com.itdragon.controller;import?org.springframework.stereotype.Controller; import?org.springframework.web.bind.annotation.PathVariable; import?org.springframework.web.bind.annotation.RequestMapping;@Controller public?class?PageController?{/***?打開(kāi)首頁(yè)*/@RequestMapping("/")public?String?showIndex()?{return?"index";}@RequestMapping("/{page}")public?String?showpage(@PathVariable?String?page)?{System.out.println("page?:?"?+?page);return?page;} }負(fù)責(zé)圖片上傳的 PictureController.java
package?com.itdragon.controller;import?java.util.Map;import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.web.bind.annotation.RequestMapping; import?org.springframework.web.bind.annotation.RequestParam; import?org.springframework.web.bind.annotation.RestController; import?org.springframework.web.multipart.MultipartFile;import?com.fasterxml.jackson.core.JsonProcessingException; import?com.fasterxml.jackson.databind.ObjectMapper; import?com.itdragon.service.PictureService;@RestController public?class?PictureController?{@Autowiredprivate?PictureService?pictureService;@RequestMapping("pic/upload")public?String?pictureUpload(@RequestParam(value?=?"fileUpload")?MultipartFile?uploadFile)?{String?json?=?"";try?{Map?result?=?pictureService.uploadPicture(uploadFile);//?瀏覽器擅長(zhǎng)處理json格式的字符串,為了減少因?yàn)闉g覽器內(nèi)核不同導(dǎo)致的bug,建議用jsonjson?=?new?ObjectMapper().writeValueAsString(result);}?catch?(JsonProcessingException?e)?{e.printStackTrace();}return?json;} }說(shuō)明:
-
@RestController 也是Spring4 提供的,是 @Controller + @ResponseBody 的組合注解。
-
Controller層的返回值是一個(gè)json格式的字符串。是考慮到瀏覽器對(duì)json解析兼容性比較好。
Views視圖層
負(fù)責(zé)上傳圖片的jsp頁(yè)面 pic-upload.jsp
<%@?page?language="java"?contentType="text/html;?UTF-8"?pageEncoding="UTF-8"%> <!DOCTYPE?html> <html> <head> <meta?http-equiv="Content-Type"?content="text/html;?charset=UTF-8"> <title>ITDragon?圖片上傳</title> </head><link?href="/js/kindeditor-4.1.10/themes/default/default.css"?type="text/css"?rel="stylesheet"><script?type="text/javascript"?src="js/jquery.min.js"></script>?<script?type="text/javascript"?charset="utf-8"?src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script><script?type="text/javascript"?charset="utf-8"?src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script> </head>?? <body>??<h3>測(cè)試上傳圖片功能接口的form表單</h3><form?action="pic/upload"?method="post"?enctype="multipart/form-data"><input?type="file"?name="fileUpload"?/><input?type="submit"?value="上傳文件"?/></form><hr?/><h3>借用KindEditor富文本編輯器實(shí)現(xiàn)批量上傳圖片</h3><textarea?id="kindEditorDesc"?style="width:800px;height:300px;visibility:hidden;"></textarea><script?type="text/javascript">$(function(){//初始化富文本編輯器KindEditor.create("#kindEditorDesc",?{//?name值,必須和Controller?的參數(shù)對(duì)應(yīng),不然會(huì)提示?400?的錯(cuò)誤filePostName?:?"fileUpload",//?action值,uploadJson?:?'/pic/upload',//?設(shè)置上傳類型,分別為image、flash、media、filedir?:?"image"});});</script>??? </body> </html>說(shuō)明:pic-upload.jsp 分為兩個(gè)部分,第一個(gè)部分是為了測(cè)試上傳圖片功能的form表單。第二個(gè)部分是為了更好的體驗(yàn)上傳,批量上傳,回顯功能的KindEditer 富文本編輯器。
總結(jié)
-
Nginx 搭建服務(wù)器的思維
-
Java實(shí)現(xiàn) Ftp上傳圖片的功能
-
KindEditer 上傳圖片的功能
源碼:https://github.com/ITDragonBlog/daydayup/tree/master/Nginx
Nginx 搭建圖片服務(wù)器到這里就結(jié)束了,有什么不足的地方,請(qǐng)賜教。如果覺(jué)得不錯(cuò),可以點(diǎn)個(gè)贊哦!
總結(jié)
以上是生活随笔為你收集整理的Nginx 搭建图片服务器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 记下来 Spring 装配 Bean 的
- 下一篇: 图解:从单个服务器扩展到百万用户的系统