您的位置:首页 > 其它

如何实现集群环境图片上传

2016-12-31 09:45 281 查看
      最近做一个电商的项目,需要实现一个图片上传的功能。图片上传的方式与传统的方式有些不同,传统的方式合适项目不大的情况下,只需要部署一个tomcat,可以将图片放到工程中;然而,图片的这种存放方式在集群的环境下,会出现找不到图片的情况。

      那么,如何解决集群环境图片上传问题呢?

      如果有一台专门的图片服务器处理图片,访问的时候只需要访问图片服务器即可,这样是不是便可以解决问题。

集群图片上传问题背景

      项目比较大时需要部署tomcat集群,如果把图片放到工程中,在集群环境下,会出现找不到图片的情况。例如:上传图片时可能是tomcat1提供服务,访问图片时负载均衡轮询时有可能是tomcat2提供服务这样出现找不到图片的情况。解决思路:访问图片直接访问图片服务器即可。

集群图片上传解决方案

      使用图片服务器:Nginx,提供http服务;

      图片保存的位置:将图片保存的路径保存到数据库中;

      如何将图片放到图片服务器上:使用ftp服务上传图片,用linux自带的htp服务器vsftp。

集群图片上图项目实现

      一、把ftp代码封装,便于复用

/**
* Description: 向FTP服务器上传文件
* @param host FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param basePath FTP服务器基础目录
* @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
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;
}

      二、相关的js,主要完成两件事:绑定事件;初始化参数
// 初始化图片上传组件
initPicUpload : function(data){
$(".picFileUpload").each(function(i,e){
var _ele = $(e);
_ele.siblings("div.pics").remove();
_ele.after('\
<div class="pics">\
<ul></ul>\
</div>');
// 回显图片
if(data && data.pics){
var imgs = data.pics.split(",");
for(var i in imgs){
if($.trim(imgs[i]).length > 0){
_ele.siblings(".pics").find("ul").append("<li><a href='"+imgs[i]+"' target='_blank'><img src='"+imgs[i]+"' width='80' height='50' /></a></li>");
}
}
}
var TT = TAOTAO = {
// 编辑器参数
kingEditorParams : {
//指定上传文件参数名称
filePostName  : "uploadFile",
//指定上传文件请求的url。
uploadJson : '/pic/upload',
//上传类型,分别为image、flash、media、file
dir : "image"
}


      三、Service功能,接收controller层传递过来的图片对象,一个文件MultiPartFile对象,把图片上传到ftp服务器。给图片生成一个新的名字。返回新文件的上传的url路径。包装成为相应的json的格式。需要保证图片插件上传要求的格式,参数:MultiPartFile uploadFile。
/**
* 图片上传服务
* @author zhuoling
* @date 2016年12月28日
* @version 1.0
*/
public class PictureServiceImpl implements PictureService {

@Value("FTP_ADDRESS")
private String FTP_ADDRESS;
@Value("FTP_PORT")
private Integer FTP_PORT;
@Value("FTP_USERNAME")
private String FTP_USERNAME;
@Value("FTP_PASSWORD")
private String FTP_PASSWORD;
@Value("FTP_BASE_PATH")
private String FTP_BASE_PATH;
@Value("IMAGE_BASE_URL")
private String IMAGE_BASE_URL;
@Value("REST_BASE_URL")
private String REST_BASE_URL;
@Value("REST_CONTENT_SYNC_URL")
private String REST_CONTENT_SYNC_URL;

@Override
public Map uploadPicture(MultipartFile uploadFile) {
Map resultMap = new HashMap<>();
try {
//生成一个新的文件名
//取原始文件名
String oldName = uploadFile.getOriginalFilename();
//生成新的文件名
//UUID.randomUUID();
String newName = IDUtils.genImageName();
newName = newName + oldName.substring(oldName.lastIndexOf(".")); //截取文件类型
//图片上传
String imagePath = new DateTime().toString("/yyyy/MM/dd");
boolean result = FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD,
FTP_BASE_PATH, imagePath, newName, uploadFile.getInputStream());
//返回结果
if(!result){
resultMap.put("error", 1);
resultMap.put("message", "文件上传失败");
return resultMap;
}
resultMap.put("error", 0);
resultMap.put("url", IMAGE_BASE_URL + imagePath + "/" + newName);
return resultMap;
} catch (Exception e) {
resultMap.put("error", 1);
resultMap.put("message", "文件上传发生异常");
return resultMap;
}
//return null;
}

}

      四、Controller功能,接收页面传递过来的图片。调用service上传到图片服务器,返回结果。参数:MultiPartFile uploadFile,返回值:返回json数据。
@Controller
public class PictureController {
@Autowired
private PictureService pictureService;

@RequestMapping("/pic/upload")
@ResponseBody
public String pictureUpload(MultipartFile uploadFile){
Map result = pictureService.uploadPicture(uploadFile);
//为了保证功能的兼容性,需要把Result转换成json格式的字符串
String json = JsonUtils.objectToJson(result);
return json;
}
}

      其中,上传方法中FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, FTP_BASE_PATH等参数交给配置文件灵活管理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: