Springmvc+kindeditor+Nginx+tomcat实现附件附件分离处理
一. 原理
kindeditor复制上传图片--》web控制器MultipartFile获取到图片--》CloseableHttpClient方式将附件提交至附件处理远程服务器--》远程服务器Tomcat(也可以使用nginx)部署web附件处理后台--》远程附件服务器使用nginx映射静态文件提供附件的下载于查看
二. kindeditor复制上传图片
KindEditor.ready(function(K) { var editor1 = K.create('textarea[name="content1"]', { cssPath : '<%=request.getContextPath()%>/kindeditor/plugins/code/prettify.css', uploadJson : '<%=request.getContextPath()%>/files/upload.do', allowFileManager : true, afterCreate : function() { var self = this; K.ctrl(document, 13, function() { self.sync(); document.forms['example'].submit(); }); K.ctrl(self.edit.doc, 13, function() { self.sync(); document.forms['example'].submit(); }); } }); prettyPrint(); });
三. web控制器MultipartFile获取到图片,通过CloseableHttpClient方式将附件提交至附件处理远程服务器
配置内容:
常量:
/* * 文件存储服务器地址 */ public static String FILE_SERVER_URL=""; /* * 文件下载查看地址 */ public static String FILE_VIEW_URL=""; /* * 文件服务器toekn */ public static String FILE_SERVER_TOKEN="";
控制器:
@ResponseBody
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
public void upload(@RequestParam(value = "imgFile", required = false) MultipartFile file,HttpServletRequest request,HttpServletResponse response) throws Exception {
注:kindeditor文本编辑器附件上传id都是imgFile,复制图片隐藏的附件上传id也是
JSONObject succMap = new JSONObject();
if(file.getSize()==0){
succMap.put("error", 1);
succMap.put("msg", "附件内容为空!");
}
if (file!=null&&!file.isEmpty()) {
String suffix=file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
Boolean isLegal=Arrays.asList(Constant.FILEEXTENSION).contains(suffix.toLowerCase());
if(file.getSize()>1024*1024*10){
succMap.put("error", 1);
succMap.put("msg", "文件大于10M!");
}else if(file.getOriginalFilename().getBytes("utf-8").length>50){
succMap.put("error", 1);
succMap.put("msg", "文件名超过50个字符!");
}else if (!isLegal) {
succMap.put("error", 1);
succMap.put("msg", "文件格式错误!");
}else{
Date date=new Date();
SimpleDateFormat datePathFormat = new SimpleDateFormat("yyyyMM");
String path=datePathFormat.format(date);
String storeName=service.tx_getFilesId()+suffix;
String url="/"+path+"/"+storeName;
String furl = UUID.randomUUID().toString() + suffix;
//因为transferTo只能将文件存储至硬盘位置,无法存储至服务器,而httpPost可以
//所以先将文件临时存放至项目路径
String tempPath = request.getRealPath("/temp/"+storeName);
File tempFile = new File(tempPath);
file.transferTo(tempFile);
//将临时存放的文件存入远程nginx文件路径(httpPost方法需要file文件,这个file变量不可以是文件流,只能是有路径的文件,所以上面需要先存放临时文件)
int res_code = PostFileToRemote(furl, tempFile,url); //调用PostFileToRemote方法
//删除临时文件
tempFile.delete();
succMap.put("error", 0);
succMap.put("url", Constant.FILE_VIEW_URL+url);
}
}
PrintWriter out = response.getWriter();
out.print(succMap.toJSONString());
out.close();
}
/** * 上传文件至远程服务器 */ public int PostFileToRemote(String uuidName, File file,String path) throws Exception{ int code =500; CloseableHttpClient httpclient = HttpClients.createDefault(); //创建一个httpclient try { HttpPost httppost = new HttpPost(Constant.FILE_SERVER_URL); //REMOTE_FILESERVER_UPLOAD_URL此路径写在Constant类里面 HttpEntity reqEntity = MultipartEntityBuilder.create() .addPart("token", new StringBody(Constant.FILE_SERVER_TOKEN,ContentType.TEXT_PLAIN))//token验证 .addPart("path", new StringBody(path,ContentType.TEXT_PLAIN)) .addPart("bin", new FileBody(file, ContentType.APPLICATION_OCTET_STREAM,file.getName())) .build(); httppost.setEntity(reqEntity); CloseableHttpResponse response = httpclient.execute(httppost); try { EntityUtils.consume(response.getEntity()); code = response.getStatusLine().getStatusCode(); } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } return code; }
四. 远程服务器Tomcat(也可以使用nginx)部署web附件处理后台
private static String token="";//与前端**进行比较 private static String url="";//存储在文件服务器的位置 @ResponseBody @RequestMapping(value = "/upload", method = RequestMethod.POST) public Map<String,Object> upload(HttpServletRequest req) throws IOException { Map<String,Object> retMap = new HashMap<String,Object>(); String pageToken=req.getParameter("token"); String path=req.getParameter("path");//存储相对路径,如/201902/201902120001.png //获取文件保存配置项 // 构造Properties对象 Properties properties = new Properties(); // 定义配置文件输入流 InputStream is = null; try { // 获取配置文件输入流 is = FileController.class.getResourceAsStream("/setting.properties"); // 加载配置文件 properties.load(is); // 读取配置文件 token=(String) properties.get("token");// token** url=(String) properties.get("url");// 文件保存路径 } catch (IOException e) { e.printStackTrace(); } finally { // 判断输入流是否为空 if (null != is) { try { // 关闭输入流 is.close(); } catch (IOException e) { e.printStackTrace(); } } } if(!token.equals(pageToken)){ retMap.put("result","0"); retMap.put("msg","token身份验证错误!"); }else{ CommonsMultipartResolver resolver = new CommonsMultipartResolver( req.getServletContext()); if (resolver.isMultipart(req)) { MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) req; // 取得request中的所有文件名 Iterator<String> iter = multiRequest.getFileNames(); while (iter.hasNext()) { String fileName = iter.next(); // 取得上传文件 List<MultipartFile> mfs = multiRequest.getFiles(fileName); for(MultipartFile file:mfs){ File tempFile = new File(url+path); File fileParent = tempFile.getParentFile(); if(!fileParent.exists()){ //如果存储文件的父文件夹不存在就创建 fileParent.mkdirs(); } InputStream inputStream=file.getInputStream(); FileOutputStream fos=new FileOutputStream(tempFile); byte[]buffer=new byte[1024]; int len=0; while ((len=inputStream.read(buffer))!=-1) { fos.write(buffer,0, len); } inputStream.close(); fos.close(); } } retMap.put("result","1"); retMap.put("msg","上传成功"); } } return retMap; }
五. 远程附件服务器使用nginx映射静态文件提供附件的下载于查看
location ~ .*\.(gif|jpg|jpeg|png)$ {
root html/files;
proxy_store on;
proxy_store_access user:rw group:rw all:rw;
proxy_temp_path html/files;#图片访问路径
proxy_redirect off;
proxy_set_header Host 127.0.0.1;
client_max_body_size 10m;
client_body_buffer_size 1280k;
proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;
proxy_buffer_size 40k;
proxy_buffers 40 320k;
proxy_busy_buffers_size 640k;
proxy_temp_file_write_size 640k;
if ( !-e $request_filename)
{
proxy_pass http://127.0.0.1:8079;#默认80端口
}
}