项目中编辑器采用了Umeditor,但是由于跨域的问题,上传图片不能正常使用,本文解决了Spring应用的跨域问题,Spring的项目均可以参考。
项目背景
(任何不谈背景的解决方案都是耍流)
Umeditor+spring mvc restful,前后端分离,所以域名也不同,存在跨域的问题,前端a.com,后端b.com
之前在很多地方看到了各种解决方法,然而有的是和我的情况不一致,有的是根本没有说明自己的项目背景,以及我不是很明白百度的官方文档为何是给出了后端的配置而不是给出对后端的要求即可?一个前端团队为何还要干预后端的事情呢?在前后端分离的情况下,难道不应该是前后端遵循统一的规范就好了吗?
解决方案
首先,后端配置允许跨域请求,在某个有@Configuration的配置类中添加:
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry)
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE");
}
};
}
之后修改umeditor.config.js
//图片上传配置区
imageUrl:"http://b.com/picture" //图片上传提交地址
imagePath:"http://b.com/file/" //图片修正地址,引用了fixedImagePath,如有特殊需求,可自行配置
imageFieldName:"upfile" //图片数据的key,若此处修改,需要在后台对应文件修改对应参数
解释:imageUrl为图片上传的提交地址,而参数的名字(后台匹配的requestparam)是imageFieldName,imagePath是图片修正地址,意思是图片上传到后台后,会返回一串字符串(restful形式,返回到response中),其中的url字段将会拼接在imagePath后形成picsrc,这个picsrc会成为图片的请求地址(即http://b.com/file/url )
最后,撰写后台代码如下:
package com.uvlab.sitespot.io;
import com.uvlab.sitespot.init.JxAppFoundation;
import com.uvlab.sitespot.service.JxAppService;
import com.uvlab.sitespot.service.fdb.JxNode;
import com.wordnik.swagger.annotations.ApiOperation;
import org.json.JSONObject;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
/**
* Created by Jys on 2016/5/14 0014.
*/
@CrossOrigin
@RestController
public class JxWikiController {
@RequestMapping(value = "/picture",method = RequestMethod.POST)
public String uploadPicture(@RequestParam("upfile") MultipartFile file,HttpServletRequest request,HttpServletResponse response){
response.setContentType("text/html; charset=utf-8"); //以下为允许跨域的一些设置
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("x-frame-options", "ALLOW-FROM *");
response.addHeader("Content-Security-Policy","frame-ancestors *");
response.setHeader("Access-Control-Allow-Headers","Access-Control");
String originname=file.getOriginalFilename();
int doc=originname.lastIndexOf(".");
String suffix=originname.substring(doc); //得到后缀名
String uuid= UUID.randomUUID().toString(); //使用uuid命名新文件
String finalname= JxAppFoundation.WikiFile+uuid+suffix; //新文件的存储位置全路径名
BufferedOutputStream stream = null;
try {
stream = new BufferedOutputStream(
new FileOutputStream(new File(finalname)));
FileCopyUtils.copy(file.getInputStream(), stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
long size=file.getSize();
String ret=String.format("{\"originalName\":\"%s\"," +
"\"name\":\"%s\"," +
"\"url\":\"%s\"," +
"\"size\":\"%s\"," +
"\"type\":\"%s\"," +
"\"state\":\"%s\"}",
originname,uuid+suffix,uuid+suffix,Long.toString(size),suffix,"SUCCESS"); //返回字符串,返回的url参数为新文件名
return ret;
}
@RequestMapping(value = "/file/{path:.+}",method = RequestMethod.GET)//这里的path即上一步返回的url
public void getPicture(@PathVariable(value = "path")String path,HttpServletResponse response){
FileInputStream in = null;
OutputStream out = null;
try {
File file = new File(JxAppFoundation.WikiFile + path); //获取文件
in = new FileInputStream(file);
byte[] b = new byte[(int) file.length()];
in.read(b);
in.close();
response.setContentType("image/*");
out = response.getOutputStream(); //文件写入到response
out.write(b);
out.flush();
out.close();
} catch (IllegalArgumentException | SecurityException | IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null)
in.close();
if (out != null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结
以上方案解决了图片的插入和显示问题,对于跨域的处理,由于umeditor对于拖入图片和点击打开对话框选择的处理方法不同,拖入和粘贴都可以解决,但是对于点击打开插入图片的跨域问题仍未解决,待解决后修改本篇文章.各位看官如有好的方案欢迎在评论中指出,谢谢大家。