这两天开发一个项目,SpringBoot+BootStrap框架需要整合富文本编辑器完成文章发布功能。在下选择的是百度的Ueditor插件。
先上效果图
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CODEING~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1、下载Ueditor插件,我下载的是【ueditor1_4_3_3-utf8-jsp】版本,解压后拷贝到项目中
2、引入依赖、脚本
<!-- ueditor的jar包依赖 -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>cn.songxinqiang</groupId>
<artifactId>com.baidu.ueditor</artifactId>
<version>1.1.2-offical</version>
</dependency>
<!-- 页面开发 -->
<div><script id="editor" type="text/plain" style="width:100%;height:300px;"></script></div>
3、实例化编辑器并配置图片、附件上传路径
<script type="text/javascript">
//实例化编辑器
var ue = UE.getEditor(\'editor\');
UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
UE.Editor.prototype.getActionUrl = function(action) {
if (action == \'uploadimage\' || action == \'uploadscrawl\' || action == \'uploadfile\') {
return \'${app}/upload/fileUpload\';// 此路径为java后台Controller中的图片附件上传路径
} else {
return this._bkGetActionUrl.call(this, action);
}
}
//初始化编辑器内容,如果需要的话
ue.ready(function() {
ue.execCommand(\'insertHtml\',$("div").eq(0).html());// 测试:将某个div中的html作为初始化值赋进来
});
</script>
4、开发java后台处理附件方法
@Controller
@RequestMapping("upload")
public class FileUploadController {
// 图片、附件上传方法
@RequestMapping("fileUpload")
@ResponseBody
public Map<String, Object> fileUpload(@RequestParam("upfile") MultipartFile mf, HttpServletRequest request, HttpServletResponse response){
// 处理图片压缩上传、附件上传
/*
*【下面给出三种上传示例:上传文件到{阿里OSS}服务器、本地(pc)上传文件到{Linux文件服务器}、Linux环境上传文件到{Linux文件服务器}】
*/
}
}
4.1、上传文件到{阿里OSS}服务器
<!-- 阿里云OSS服务器pom.xml依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
略去阿里OSS服务器注册购买等过程
a、修改项目application.yml配置文件
################### 上传文件到阿里OSS服务器的配置 ###################
OSS:
ENDPOINT: ******
ACCESSKEYID: ******
ACCESSKEYSECRET: ******
BUCKETNAME: ******
CALLBACK: ******
说明:CALLBACK是图片、文件回访的域名,如果未购买域名,可以用BUCKETNAME拼接出回访url
例:String url = OSSUtil.getBUCKETNAME()+"."+OSSUtil.getENDPOINT()+"/"+fileName
b、以下是SpringBoot读取配置文件到自定义Util中的过程
// 自定义OSSUtil工具类
public class OSSUtil{
/**
* 访问OSS的域名
*/
public static String ENDPOINT;
/**
* 访问OSS的标识
*/
public static String ACCESSKEYID;
/**
* 访问OSS的密钥
*/
public static String ACCESSKEYSECRET;
/**
* 访问OSS的Object存储空间
*/
public static String BUCKETNAME;
/**
* 回调地址
*/
public static String CALLBACK;
// 省略get、set方法
}
// 新建Config类,用于在SpringBoot项目启动时 将application.yml中的配置写入到新建的OSSUtil属性中
@Configuration
public class OSSFileUploadConfig {
/**
* 访问OSS的域名
*/
@Value("${OSS.ENDPOINT}")
public String ENDPOINT;
/**
* 访问OSS的密钥
*/
@Value("${OSS.ACCESSKEYID}")
public String ACCESSKEYID;
/**
* 访问OSS的密钥
*/
@Value("${OSS.ACCESSKEYSECRET}")
public String ACCESSKEYSECRET;
/**
* 访问OSS的Object存储空间
*/
@Value("${OSS.BUCKETNAME}")
public String BUCKETNAME;
/**
* 回调地址
* @return
*/
@Value("${OSS.CALLBACK}")
public String CALLBACK;
@Bean
public int initStatic(){
OSSUtil.setENDPOINT(this.ENDPOINT);
OSSUtil.setACCESSKEYID(this.ACCESSKEYID);
OSSUtil.setACCESSKEYSECRET(this.ACCESSKEYSECRET);
OSSUtil.setBUCKETNAME(this.BUCKETNAME);
OSSUtil.setCALLBACK(this.CALLBACK);
return 0;
}
}
c、图片|附件上传方法
@RequestMapping("fileUpload")
@ResponseBody
public Map<String, Object> fileUpload(@RequestParam("upfile") MultipartFile mf, HttpServletRequest request, HttpServletResponse response){
Map<String, Object> result = new HashMap<String, Object>();
result.put("state", "SUCCESS");
result.put("message", "文件上传成功!");
String endpoint = OSSUtil.getENDPOINT()+"/";
OSSClient ossClient = new OSSClient(OSSUtil.URL+endpoint, OSSUtil.getACCESSKEYID(), OSSUtil.getACCESSKEYSECRET());
try {
// 判断Bucket是否存在。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
if (ossClient.doesBucketExist(OSSUtil.getBUCKETNAME())) {
System.out.println("您已经创建Bucket:" + OSSUtil.getBUCKETNAME() + "。");
} else {
System.out.println("您的Bucket不存在,创建Bucket:" + OSSUtil.getBUCKETNAME() + "。");
// 创建Bucket。详细请参看“SDK手册 > Java-SDK > 管理Bucket”。
// 链接地址是:https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_bucket.html?spm=5176.docoss/sdk/java-sdk/init
ossClient.createBucket(OSSUtil.getBUCKETNAME());
}
String fileName = mf.getOriginalFilename(); // 文件名称{为防止文件覆盖,最好将名称加上时间戳}
String FILE_SUFFIX = ".jpg,.jpeg,.png,.gif"; // 图片文件的后缀
String fileSuffix = fileName.substring(oldFileName.lastIndexOf(".")+1); // 上传文件的后缀名
if(ImageUtil.FILE_SUFFIX.contains(fileSuffix)){// 如果是图片文件,可以考虑压缩尺寸后再存储到OSS服务器
BufferedImage image = ImageIO.read(mf.getInputStream());// 所上传的图片文件转换为BufferedImage,便于重绘
Integer imageWidth = image.getWidth();// 图片宽度
Integer imageHeight = image.getHeight();// 图片高度
Integer targetWidth = 500;// 目标图片宽度
Integer targetHeight = 300;// 目标图片高度
if(imageWidth > targetWidth || imageHeight > targetHeight){// 如果上传的图片尺寸大于目标设置的尺寸,则将图片重绘
Integer newWidth = 0, newHeight = 0;
if(imageWidth > targetWidth && imageWidth > imageHeight) {
newWidth = targetWidth;
newHeight = Integer.parseInt(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(targetWidth), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}else if(imageHeight > targetHeight){
newHeight = targetHeight;
newWidth = Integer.parseInt(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(targetHeight), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}
BufferedImage newImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);// 以RGB模式创建新的图片
newImage.getGraphics().drawImage(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(newImage, fileSuffix, imgOut);
InputStream is = new ByteArrayInputStream(bs.toByteArray());
ossClient.putObject(OSSUtil.getBUCKETNAME(), fileName, is);// 写文件到OSS服务器
}else{// 小尺寸图片,不用压缩
InputStream is = new ByteArrayInputStream(mf.getBytes());
ossClient.putObject(OSSUtil.getBUCKETNAME(), fileName, is);// 写文件到OSS服务器
}
}else{// 非图片文件,如word、pdf等直接存储到OSS服务器
InputStream is = new ByteArrayInputStream(mf.getBytes());
ossClient.putObject(OSSUtil.getBUCKETNAME(), fileName, is);// 写文件到OSS服务器
}
String url = OSSUtil.getCALLBACK() + "/" + fileName;// 文件回访路径
result.put("url", url);
result.put("title", fileName);
result.put("original", url);
} catch (Excaption e){
result.put("state", "ERROR");
result.put("message", "文件上传失败!");
} finally {
ossClient.shutdown();
}
return result;
}
4.2、pc环境上传文件到Linux服务器
<!-- pc端上传文件到Linux服务器 依赖 -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.48</version>
</dependency>
@RequestMapping(value = "/fileUpload")
@ResponseBody
public Map<String, Object> imgUpload(@RequestParam("upfile") MultipartFile mf, HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("state", "SUCCESS");
result.put("message", "图片上传成功!");
DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Calendar calendar = Calendar.getInstance();// 当前时间
String url = "http://test.com"+sdf.format(calendar.getTime());// 回调路径
String basePath = "/opt/files/"+sdf.format(calendar.getTime());// 文件目录,每天的文件存储到单独的目录下
String ip = "0.0.0.1";// Linux服务器ip
Integer port = 22;// Linux服务器端口
String user = "admin";// Linux服务器用户名
String pwd = "123456";// Linux服务器密码
InputStream input = null;
OutputStream output = null;
try {
Session session = null;// 登陆服务器
JSch jsch = new JSch();
if (port <= 0) {
session = jsch.getSession(user, ip);// 连接服务器,采用默认端口
} else {
session = jsch.getSession(user, ip, port);// 采用指定的端口连接服务器
}
if (session == null) {// 如果服务器连接不上,则抛出异常
result.put("state", "ERROR");
result.put("message", "连接文件服务器失败!");
return result;
}
session.setPassword(pwd);// 设置登陆主机的密码
session.setConfig("StrictHostKeyChecking", "no");// 设置第一次登陆的时候提示,可选值:(ask | yes | no)
session.connect(30000000);// 设置登陆超时时间
Channel channel = (Channel) session.openChannel("sftp");// 建立 流 传输通道
channel.connect(10000000);
ChannelSftp sftp = (ChannelSftp) channel;
String oldFileName = mf.getOriginalFilename();// 文件名
int index = oldFileName.lastIndexOf(".");
String fileName = oldFileName.substring(0, 5 > index ? index : 5) + calendar.getTime() + oldFileName.substring(index);
String fileSuffix = oldFileName.substring(oldFileName.lastIndexOf(".")+1);
String FILE_SUFFIX = ".jpg,.jpeg,.png,.gif";
if(FILE_SUFFIX.contains(fileSuffix)){// 如果上传的文件是图片,则以考虑压缩尺寸
Integer targetWIdth = 500;
Integer targetHeight = 300;
BufferedImage image = ImageIO.read(mf.getInputStream());// 所上传的图片文件
Integer imageWidth = image.getWidth();
Integer imageHeight = image.getHeight();
if(targetWidth < imageWIdth || targetHeight < imageHeight){
Integer newWidth = 0, newHeight = 0;
if(targetWidth < imageWIdth && imageWidth > imageHeight){
newWidth = targetWidth;
newHeight = Integer.parseInt(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(targetWidth), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}else{
newHeight = targetHeight;
newWIdth = Integer.parseInt(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(targetHeight), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}
BufferedImage newImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);// 创建新的图片
newImage.getGraphics().drawImage(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(newImage, fileSuffix, imgOut);
input = new ByteArrayInputStream(bs.toByteArray());
}else{
input = new ByteArrayInputStream(mf.getBytes());
}
}else{
input = new ByteArrayInputStream(mf.getBytes());
}
String[] dirs = basePath.split("/");// 切换到文件最终上传目录
sftp.cd("/");
for(String dir : dirs){
if(null == dir || dir.isEmpty()) continue;
try {
sftp.cd(dir);
} catch (SftpException e) {
sftp.mkdir(dir);// 如果目录不存在,则新建目录并切换进来
sftp.cd(dir);
}
}
output = sftp.put(fileName);// 传输文件
byte[] bytes = new byte[1024];
int b;
while((b = input.read(bytes)) != -1){
output.write(bytes, 0, b);
}
url += "/"+fileName;
result.put("url", url);
result.put("title", fileName);
result.put("original", url);
} catch(Exception e){
result.put("state", "ERROR");
result.put("message", "访问图片服务器异常!!");
}finally{
try {
if(null != input){
input.close();
input = null;
}
if(null != output){
output.close();
output = null;
}
}catch(){}
}
return result;
}
4.3、Linux环境上传文件到Linux服务器[示例代码为同一台服务器,非同一台服务器可参考pc端上传代码]
@RequestMapping(value = "/fileUpload")
@ResponseBody
public Map<String, Object> imgUpload(@RequestParam("upfile") MultipartFile mf, HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("state", "SUCCESS");
result.put("message", "图片上传成功!");
DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Calendar calendar = Calendar.getInstance();// 当前时间
String url = "http://test.com"+sdf.format(calendar.getTime());// 回调路径
String basePath = "/opt/files/"+sdf.format(calendar.getTime());// 文件目录,每天的文件存储到单独的目录下
InputStream input = null;
OutputStream output = null;
try {
String oldFileName = mf.getOriginalFilename();// 文件名
int index = oldFileName.lastIndexOf(".");
String fileName = oldFileName.substring(0, 5 > index ? index : 5) + calendar.getTime() + oldFileName.substring(index);
String fileSuffix = oldFileName.substring(oldFileName.lastIndexOf(".")+1);
String FILE_SUFFIX = ".jpg,.jpeg,.png,.gif";
if(FILE_SUFFIX.contains(fileSuffix)){// 如果上传的文件是图片,则以考虑压缩尺寸
Integer targetWIdth = 500;
Integer targetHeight = 300;
BufferedImage image = ImageIO.read(mf.getInputStream());// 所上传的图片文件
Integer imageWidth = image.getWidth();
Integer imageHeight = image.getHeight();
if(targetWidth < imageWIdth || targetHeight < imageHeight){
Integer newWidth = 0, newHeight = 0;
if(targetWidth < imageWIdth && imageWidth > imageHeight){
newWidth = targetWidth;
newHeight = Integer.parseInt(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(targetWidth), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}else{
newHeight = targetHeight;
newWIdth = Integer.parseInt(BigDecimal.valueOf(imageWidth).divide(BigDecimal.valueOf(imageHeight).divide(BigDecimal.valueOf(targetHeight), 8, BigDecimal.ROUND_HALF_UP), 0, BigDecimal.ROUND_HALF_UP)+"");
}
BufferedImage newImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);// 创建新的图片
newImage.getGraphics().drawImage(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(newImage, fileSuffix, imgOut);
input = new ByteArrayInputStream(bs.toByteArray());
}else{
input = new ByteArrayInputStream(mf.getBytes());
}
}else{
input = new ByteArrayInputStream(mf.getBytes());
}
File file = new File(basePath);// 传输文件目录
if(!file.exists()){
file.mkdirs();
}
output = new FileOutputStream(basePath + "/" + fileName);// 传输文件
byte[] bytes = new byte[1024];
int b;
while((b = input.read(bytes)) != -1){
output.write(bytes, 0, b);
}
url += "/"+fileName;
result.put("url", url);
result.put("title", fileName);
result.put("original", url);
} catch(Exception e){
result.put("state", "ERROR");
result.put("message", "访问图片服务器异常!!");
}finally{
try {
if(null != input){
input.close();
input = null;
}
if(null != output){
output.close();
output = null;
}
}catch(){}
}
return result;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~代码为手写,可能不完善,但功能可以实现~~~~~~~~~~~~~~~~~~~~~~~~~~~~~