图片服务器的完成:在文件中的3个pdf文件。一个vm 一个镜像。
Nginx
有关nginx的内容:http://blog.csdn.net/xlgen157387/article/details/49781487
vsftpd
有关vsftpd的内容:http://blog.csdn.net/wave_1102/article/details/50651433
测试图片服务器:
先验证 JAVA 代码上传图片到 FTP 服务器:
测试显示上传成功。
打开FileZilla Client工具,连接到虚拟机
可以看到在虚拟机中 有刚才java代码上传的图片。
基于这个使用在 jingxi-common 中新建一个公共类来提高代码的服用:
package com.jingxi.common.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; /** * * Description: 向FTP服务器上传文件 * * @paramhost FTP服务器hostname * * @paramport FTP服务器端口 * * @paramusername FTP登录账号 * * @parampassword FTP登录密码 * * @parambasePath FTP服务器基础目录 * @paramfilePath FTP服务器文件存放路径。 * 例如分日期存放:/2017/01/01。文件的路径为basePath+filePath * * @paramfilename 上传到FTP服务器上的文件名 * * @paraminput 输入流 * * @return成功返回true,否则返回false */ public class FtpUtil { public static boolean uploadFile(String host, int port, String username, String password, String basePath,String filePath, String filename, InputStream input) { boolean result= false; FTPClient ftp= new FTPClient(); try{ int reply; ftp.connect(host, port);// 连接FTP服务器 // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器 ftp.login(username, password); // 登录 reply= ftp.getReplyCode(); if(!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } //切换到上传目录 if(!ftp.changeWorkingDirectory(basePath+filePath)) { //如果目录不存在创建目录 String[] dirs= filePath.split("/"); String tempPath= basePath; for(String dir: dirs) { if(null== dir|| "".equals(dir)) continue; tempPath+= "/"+ dir; if(!ftp.changeWorkingDirectory(tempPath)) { if(!ftp.makeDirectory(tempPath)) { return result; } else{ ftp.changeWorkingDirectory(tempPath); } } } } //设置上传文件的类型为二进制类型 ftp.setFileType(FTP.BINARY_FILE_TYPE); //上传文件 if(!ftp.storeFile(filename, input)) { return result; } input.close(); ftp.logout(); result= true; } catch(IOException e) { e.printStackTrace(); } finally{ if(ftp.isConnected()) { try{ ftp.disconnect(); } catch(IOException ioe) { } } } return result; } /** * Description: 从FTP服务器下载文件 * * @paramhost FTP服务器hostname * * @paramport FTP服务器端口 * * @paramusername FTP登录账号 * * @parampassword FTP登录密码 * * @paramremotePath FTP服务器上的相对路径 * @paramfileName 要下载的文件名 * * @paramlocalPath 下载后保存到本地的路径 * * @return*/ public static boolean downloadFile(String host, int port, String username, String password, String remotePath,String fileName, String localPath) { boolean result= false; FTPClient ftp= new FTPClient(); try{ int reply; ftp.connect(host, port); // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器 ftp.login(username, password); // 登录 reply= ftp.getReplyCode(); if(!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; }ftp.changeWorkingDirectory(remotePath); // 转移到FTP服务器目录 FTPFile[] fs= ftp.listFiles(); for(FTPFile ff: fs) { if(ff.getName().equals(fileName)) { File localFile= new File(localPath+ "/"+ ff.getName()); OutputStream is= new FileOutputStream(localFile); ftp.retrieveFile(ff.getName(), is); is.close(); } } ftp.logout(); result= true; } catch(IOException e) { e.printStackTrace(); } finally{ if(ftp.isConnected()) { try{ ftp.disconnect(); } catch(IOException ioe) { } } } return result; } public static void main(String[] args) { try{ FileInputStream in=new FileInputStream(new File("E:\\2.jpg")); boolean flag= uploadFile("192.168.63.128", 21, "ftpuser", "123qweqwe", "/home/ftpuser/images","", "2.jpg", in); System.out.println(flag); } catch(FileNotFoundException e) { e.printStackTrace(); } } }
在jingxi-backend-controller中加入vsftpd的各种配置信息:
图片上传功能的实现:
i. 客户端脚本实现
有关kindeditor的用法:http://www.cnblogs.com/red-code/p/5743147.html
ii. Service 层
入参:接收 Controller 传递过来的 MultiPartFile 对象。返回: KindEditor 要求的 Json 数据格式。参见下面地址:
http://kindeditor.net/docs/upload.html
按照上图定义数据格式,使用 Map 来实现,Map 中的内容:
Key | Value |
Error | 1 / 0 |
url | 图片的 url 地址(成功时) |
message | 错误信息(失败时) |
在jingxi-common中建立一个工具类 用来生成图片的名字。
package com.jingxi.service; import java.util.HashMap; import java.util.Map; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import com.jingxi.common.util.FtpUtil; import com.jingxi.common.util.IDUtil; @Service public class ImageUploadServiceImpl implements ImageUploadService { @Value("${FILE_UPLOAD_PATH}") private String FILE_UPLOAD_PATH; @Value("${FTP_SERVER_IP}") private String FTP_SERVER_IP; @Value("${FTP_SERVER_PORT}") private Integer FTP_SERVER_PORT; @Value("${FTP_SERVER_USERNAME}") private String FTP_SERVER_USERNAME; @Value("${FTP_SERVER_PASSWORD}") private String FTP_SERVER_PASSWORD; @Value("${IMAGE_BASE_URL}") private String IMAGE_BASE_URL; @SuppressWarnings({"unchecked","rawtypes"}) @Override public Map uploadFile(MultipartFile uploadFile) throws Exception { Map resultMap =new HashMap();//新建一个hashmap try{ //判断文件是否为空 if(uploadFile.isEmpty()) return null; //上传文件以日期为单位分开存放,可以提高图片的查询速度 String filePath=new DateTime().toString("/yyyy/MM/dd"); //取初始文件名 String originalFilename =uploadFile.getOriginalFilename(); //新文件名 String newFileName=IDUtil.genImageName() + originalFilename.substring(originalFilename.lastIndexOf(".")); //转存文件,上传到ftp服务器 Boolean isSuccessed=FtpUtil.uploadFile(FTP_SERVER_IP, FTP_SERVER_PORT, FTP_SERVER_USERNAME, FTP_SERVER_PASSWORD, FILE_UPLOAD_PATH, filePath, newFileName, uploadFile.getInputStream()); String path=filePath +"/"+newFileName; if(isSuccessed){ resultMap.put("error", 0); resultMap.put("url", IMAGE_BASE_URL+path); }else{ resultMap.put("error", 1); resultMap.put("message", "图片上传失败"); } }catch(Exception e){ e.printStackTrace(); } return resultMap; } }
iii. Controller 层
在 SpringMVC 的配置文件上配置文件上传:
Contoller 代码实现:
测试该功能:
至此,图片服务器以及图片上传功能完成。