1.application.properties文件配置
#FTP文件上传 #ftp config ftp.enabled=true ftp.host=127.0.0.1 ftp.port=21 ftp.username=zz ftp.password=123456 ftp_img_path=/home/zz/img/ ftp_file_path=/home/zz/file/ ftp_img_show_path=/img/ ftp_file_show_path=/file/2.ftp配置类
package com.config; import javax.annotation.PreDestroy; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import com.cwh.springbootMybatis.utils.FtpUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; /** * FTP配置类 * * */ @Slf4j @Configuration @ConditionalOnClass({GenericObjectPool.class, FTPClient.class}) @ConditionalOnProperty(value = "ftp.enabled", havingValue = "true") @EnableConfigurationProperties(FTPConfiguration.FtpConfigProperties.class) public class FTPConfiguration { private ObjectPool<FTPClient> pool; public FTPConfiguration(FtpConfigProperties props) { // 默认最大连接数与最大空闲连接数都为8,最小空闲连接数为0 // 其他未设置属性使用默认值,可根据需要添加相关配置 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setTestOnBorrow(true); poolConfig.setTestOnReturn(true); poolConfig.setTestWhileIdle(true); //poolConfig.setMaxWaitMillis(-1);//永不超时 //连接空闲的最小时间,达到此值后空闲连接将可能会被移除。默认为1000L 60L 30L poolConfig.setMinEvictableIdleTimeMillis(1000*60*30);//1000L 60L 30L 60000 //连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留minIdle个空闲连接数。默认为-1. poolConfig.setSoftMinEvictableIdleTimeMillis(-1);//-1 50000 //空闲链接检测线程检测的周期,毫秒数。如果为负值,表示不运行检测线程。默认为-1. poolConfig.setTimeBetweenEvictionRunsMillis(-1);//30000 pool = new GenericObjectPool<>(new FtpClientPooledObjectFactory(props), poolConfig); preLoadingFtpClient(props.getInitialSize(), poolConfig.getMaxIdle()); // 初始化ftp工具类中的ftpClientPool FtpUtil.init(pool); } /** * 预先加载FTPClient连接到对象池中 * @param initialSize 初始化连接数 * @param maxIdle 最大空闲连接数 */ private void preLoadingFtpClient(Integer initialSize, int maxIdle) { if (initialSize == null || initialSize <= 0) { return; } int size = Math.min(initialSize.intValue(), maxIdle); for (int i = 0; i < size; i++) { try { pool.addObject(); } catch (Exception e) { log.error("preLoadingFtpClient error...", e); } } } @PreDestroy public void destroy() { if (pool != null) { pool.close(); log.info("销毁ftpClientPool..."); } } /** * Ftp配置属性类,建立ftpClient时使用 */ @Data @ConfigurationProperties(prefix = "ftp") static class FtpConfigProperties { private String host = "localhost"; private int port = FTPClient.DEFAULT_PORT; private String username; private String password; private int bufferSize = 8096; private String encoding="UTF-8"; /** * 初始化连接数 */ private Integer initialSize = 0; } /** * FtpClient对象工厂类 */ static class FtpClientPooledObjectFactory implements PooledObjectFactory<FTPClient> { private FtpConfigProperties props; public FtpClientPooledObjectFactory(FtpConfigProperties props) { this.props = props; } @Override public PooledObject<FTPClient> makeObject() throws Exception { FTPClient ftpClient = new FTPClient(); try { long time=System.currentTimeMillis(); ftpClient.connect(props.getHost(), props.getPort()); ftpClient.login(props.getUsername(), props.getPassword()); log.info("连接FTP服务器返回码{}", ftpClient.getReplyCode()); ftpClient.setBufferSize(props.getBufferSize()); ftpClient.setControlEncoding(props.getEncoding()); ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); log.info("登录耗时 "+(System.currentTimeMillis()-time)+" ms!"); return new DefaultPooledObject<>(ftpClient); } catch (Exception e) { log.error("建立FTP连接失败", e); if (ftpClient.isAvailable()) { ftpClient.disconnect(); } ftpClient = null; throw new Exception("建立FTP连接失败", e); } } @Override public void destroyObject(PooledObject<FTPClient> p) throws Exception { FTPClient ftpClient = getObject(p); if (ftpClient != null && ftpClient.isConnected()) { ftpClient.disconnect(); } } @Override public boolean validateObject(PooledObject<FTPClient> p) { FTPClient ftpClient = getObject(p); if (ftpClient == null || !ftpClient.isConnected()) { return false; } try { ftpClient.changeWorkingDirectory("/"); return true; } catch (Exception e) { log.error("验证FTP连接失败::{}", ExceptionUtils.getStackTrace(e)); return false; } } @Override public void activateObject(PooledObject<FTPClient> p) throws Exception { } @Override public void passivateObject(PooledObject<FTPClient> p) throws Exception { } private FTPClient getObject(PooledObject<FTPClient> p) { if (p == null || p.getObject() == null) { return null; } return p.getObject(); } } }3.ftp工具类
package com.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import java.util.UUID; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.pool2.ObjectPool; import org.apache.shiro.util.Assert; import org.springframework.stereotype.Component; import lombok.extern.slf4j.Slf4j; /*** * ftp上传下载工具类 * * @author * */ @Component @Slf4j public class FtpUtil { /** * ftpClient连接池初始化标志 */ private static volatile boolean hasInit = false; /** * ftpClient连接池 */ private static ObjectPool<FTPClient> ftpClientPool; /** * Description: 向FTP服务器上传文件 * @param ftpHost FTP服务器hostname * @param ftpUserName 账号 * @param ftpPassword 密码 * @param ftpPort 端口 * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa * @param fileName ftp文件名称 * @param input 文件流 * @return 成功返回true,否则返回false */ public String uploadFile(String ftpPath,String fileName,InputStream input) { FTPClient ftpClient = null; String newName=null; try { int reply; ftpClient = getFtpClient(); reply = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftpClient.disconnect(); log.debug("上传失败,连接断开了!"); } //ftpClient.setControlEncoding("UTF-8"); // 中文支持 //ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); //ftpClient.enterLocalPassiveMode(); ftpClient.changeWorkingDirectory(ftpPath); newName=getCurrentDay()+ "__"+UUID.randomUUID().toString()+fileName.substring(fileName.lastIndexOf(".", fileName.length())); //ftpClient.storeFile(fileName, input); boolean f=ftpClient.storeFile(new String(newName.getBytes("UTF-8"),"iso-8859-1"),input); if(f) { log.debug("上传成功!"); }else { log.debug("上传失败!"); } input.close(); //ftpClient.logout(); } catch (IOException e) { e.printStackTrace(); } finally { releaseFtpClient(ftpClient); } return newName; } /* * 从FTP服务器下载文件 * * @param ftpHost FTP IP地址 * @param ftpUserName FTP 用户名 * @param ftpPassword FTP用户名密码 * @param ftpPort FTP端口 * @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa * @param localPath 下载到本地的位置 格式:H:/download * @param fileName 文件名称 */ public void downloadFtpFile(String ftpPath, String localPath, String fileName) { FTPClient ftpClient = null; try { ftpClient = getFtpClient(); ftpClient.setControlEncoding("UTF-8"); // 中文支持 ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); ftpClient.changeWorkingDirectory(ftpPath); File localFile = new File(localPath + File.separatorChar + fileName); OutputStream os = new FileOutputStream(localFile); //ftpClient.retrieveFile(fileName, os); boolean f=ftpClient.retrieveFile(new String(localFile.getName().getBytes("utf-8"),"iso-8859-1"), os); System.out.println("download "+f); os.close(); //ftpClient.logout(); } catch (FileNotFoundException e) { System.out.println("没有找到" + ftpPath + "文件"); e.printStackTrace(); } catch (SocketException e) { System.out.println("连接FTP失败."); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); System.out.println("文件读取错误。"); e.printStackTrace(); } } private static String getCurrentDay() { java.text.SimpleDateFormat format = new java.text.SimpleDateFormat( "yyyy-MM-dd-HH-mm-ss"); return format.format(new java.util.Date()); } /** * 初始化ftpClientPool * * @param ftpClientPool */ public static void init(ObjectPool<FTPClient> ftpClientPool) { if (!hasInit) { synchronized (FtpUtil.class) { if (!hasInit) { FtpUtil.ftpClientPool = ftpClientPool; hasInit = true; } } } } /** * 获取ftpClient * * @return */ private static FTPClient getFtpClient() { checkFtpClientPoolAvailable(); FTPClient ftpClient = null; Exception ex = null; // 获取连接最多尝试3次 for (int i = 0; i < 3; i++) { try { ftpClient = ftpClientPool.borrowObject(); ftpClient.changeWorkingDirectory("/"); break; } catch (Exception e) { ex = e; } } if (ftpClient == null) { throw new RuntimeException("Could not get a ftpClient from the pool", ex); } return ftpClient; } /** * 释放ftpClient */ private static void releaseFtpClient(FTPClient ftpClient) { if (ftpClient == null) { return; } try { ftpClientPool.returnObject(ftpClient); } catch (Exception e) { log.error("Could not return the ftpClient to the pool", e); // destoryFtpClient if (ftpClient.isAvailable()) { try { ftpClient.disconnect(); } catch (IOException io) { } } } } /** * 检查ftpClientPool是否可用 */ private static void checkFtpClientPoolAvailable() { Assert.state(hasInit, "FTP未启用或连接失败!"); } }4.ftp controller类
package com.cwh.springbootMybatis.controller.system; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.cwh.springbootMybatis.utils.FtpUtil; import com.cwh.springbootMybatis.utils.UUIDUtil; import lombok.extern.slf4j.Slf4j; import net.sf.json.JSONObject; /** * */ @Controller @Slf4j public class UploadController { @Autowired FtpUtil ftpUtil; @Value("${ftp_img_path}") private String ftp_img_path; @RequestMapping(value = "/uploadFTP", method = RequestMethod.POST) @ResponseBody public String uploadFTP(@RequestParam("upfile") MultipartFile file,String id) throws Exception { JSONObject json = new JSONObject(); if(file == null) { log.debug("文件为空,上传失败!"); return null; } String name=ftpUtil.uploadFile(ftp_img_path, file.getOriginalFilename(), file.getInputStream()); json.put("state", "SUCCESS"); json.put("url", name); json.put("title", file.getOriginalFilename()); json.put("original", file.getOriginalFilename()); return json.toString(); } }5.页面部分代码注意百度编辑器插件的位置src/main/resources/static/lib
<head> <script type="text/javascript" charset="utf-8" src="/lib/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="/lib/ueditor/ueditor.all.min.js"> </script> </head> <body> <div class="layui-form-item layui-form-text"> <label class="layui-form-label">*资讯内容</label> <div class="layui-input-block" id="content"> </div> </div> <script type="text/javascript"> UE.getEditor('content',{ //focus时自动清空初始化时的内容 autoClearinitialContent:false, //关闭字数统计 wordCount:false, //关闭elementPath elementPathEnabled:false, //默认的编辑区域高度 initialFrameHeight:300, //initialFrameWidth:1100, enableAutoSave: false, //更多其他参数,请参考ueditor.config.js中的配置项 initialFrameWidth:1000 ,zIndex : 0// z轴 ,要设置为0,否则有下拉菜单就会被挡住 }); UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl; UE.Editor.prototype.getActionUrl = function(action) { if (action == 'uploadimage' || action == 'uploadscrawl'|| action == 'uploadfile') { var actUrl=this._bkGetActionUrl.call(this,action); //alert(actUrl); return getWebRootPath()+'uploadFTP.do';//指定访问路径 }else { return this._bkGetActionUrl.call(this, action); } } function getWebRootPath() { var a = window.document.location.href;// var b = window.document.location.pathname; var pos = a.indexOf(b); var path = a.substring(0, pos); a = a.substring(a.indexOf("/") + 2, a.length); a = a.substring(a.indexOf("/") + 1, a.length); var pathName = a.substring(0, a.indexOf("/")); //alert(path); return path + "/"; } </script> </body>6.如何获取百度编辑器的内容呢?
var content=UE.getEditor('content').getContent();7.百度编辑器配置代码
import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller @RequestMapping("/lib/ueditor") public class ConfigController { // 图片上传 跳转到配置文件 @RequestMapping(value = "/config") public void ueditor(@RequestParam("action") String action, HttpServletRequest request, HttpServletResponse response) { org.springframework.core.io.Resource res = new ClassPathResource("config/config.json"); InputStream is = null; response.setHeader("Content-Type", "text/html"); try { is = res.getInputStream(); StringBuffer sb = new StringBuffer(); byte[] b = new byte[1024]; int length = 0; while (-1 != (length = is.read(b))) { sb.append(new String(b, 0, length, "utf-8")); } String result = sb.toString().replaceAll("/\\*(.|[\\r\\n])*?\\*/", ""); net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(result); PrintWriter out = response.getWriter(); out.print(json.toString()); } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }8.百度编辑器配置json文件,注意json文件的位置 src/main/resources/config/config.json
/* 前后端通信相关的配置,注释只允许使用多行方式 */ { /* 上传图片配置项 */ "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ "imageFieldName": "upfile", /* 提交的图片表单名称 */ "imageMaxSize": 2048000, /* 上传大小限制,单位B */ "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ "imageCompressEnable": true, /* 是否压缩图片,默认是true */ "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ "imageInsertAlign": "none", /* 插入的图片浮动方式 */ "imageUrlPrefix": "http://x.x.x.x/img/", /* 图片访问路径前缀 */ "imagePathFormat": "", /* 上传保存路径,可以自定义保存路径和文件名格式 */ /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ /* {time} 会替换成时间戳 */ /* {yyyy} 会替换成四位年份 */ /* {yy} 会替换成两位年份 */ /* {mm} 会替换成两位月份 */ /* {dd} 会替换成两位日期 */ /* {hh} 会替换成两位小时 */ /* {ii} 会替换成两位分钟 */ /* {ss} 会替换成两位秒 */ /* 非法字符 \ : * ? " < > | */ /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ /* 涂鸦图片上传配置项 */ "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ "scrawlPathFormat": "", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ "scrawlUrlPrefix": "http://x.x.x.x/img/", /* 图片访问路径前缀 */ "scrawlInsertAlign": "none", /* 截图工具上传 */ "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ "snapscreenPathFormat": "", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "snapscreenUrlPrefix": "http://x.x.x.x/img/", /* 图片访问路径前缀 */ "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ /* 抓取远程图片配置 */ "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ "catcherFieldName": "source", /* 提交的图片列表表单名称 */ "catcherPathFormat": "/ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "catcherUrlPrefix": "", /* 图片访问路径前缀 */ "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ /* 上传视频配置 */ "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ "videoFieldName": "upfile", /* 提交的视频表单名称 */ "videoPathFormat": "/ueditor/jsp/upload/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "videoUrlPrefix": "", /* 视频访问路径前缀 */ "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ "videoAllowFiles": [ ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ /* 上传文件配置 */ "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ "fileFieldName": "upfile", /* 提交的文件表单名称 */ "filePathFormat": "", /* 上传保存路径,可以自定义保存路径和文件名格式 */ "fileUrlPrefix": "http://x.x.x.x/img/", /* 文件访问路径前缀 */ "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ "fileAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" ], /* 上传文件格式显示 */ /* 列出指定目录下的图片 */ "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ "imageManagerListPath": "/ueditor/jsp/upload/image/", /* 指定要列出图片的目录 */ "imageManagerListSize": 20, /* 每次列出文件数量 */ "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ /* 列出指定目录下的文件 */ "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ "fileManagerListPath": "/ueditor/jsp/upload/file/", /* 指定要列出文件的目录 */ "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ "fileManagerListSize": 20, /* 每次列出文件数量 */ "fileManagerAllowFiles": [ ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" ] /* 列出的文件类型 */ }最后注意百度编辑器文件的路径src\main\resources\static\lib\ueditor,其中ueditor就是百度编辑器的插件,下载地址
https://ueditor.baidu.com/website/