diff --git a/mallinkAdmin/pom.xml b/mallinkAdmin/pom.xml index 820d917af..3ea123daa 100644 --- a/mallinkAdmin/pom.xml +++ b/mallinkAdmin/pom.xml @@ -32,6 +32,11 @@ weixin-java-open ${weixin-java-open.version} + + commons-fileupload + commons-fileupload + 1.3.3 + diff --git a/mallinkAdmin/src/main/java/com/iformall/config/WebConfig.java b/mallinkAdmin/src/main/java/com/iformall/config/WebConfig.java index 3ede5c77f..c817424a3 100644 --- a/mallinkAdmin/src/main/java/com/iformall/config/WebConfig.java +++ b/mallinkAdmin/src/main/java/com/iformall/config/WebConfig.java @@ -7,12 +7,23 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.iformall.interceptor.RequestInterceptor; +import com.iformall.ueditor.ActionEnter; +import com.iformall.ueditor.ConfigManager; +import com.iformall.ueditor.UEditorConfig; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.*; +import javax.servlet.Filter; import java.math.BigDecimal; import java.math.BigInteger; import java.text.SimpleDateFormat; @@ -20,10 +31,49 @@ import java.util.List; @Configuration @EnableWebMvc +@EnableConfigurationProperties({UEditorConfig.class, AwsProperty.class}) public class WebConfig implements WebMvcConfigurer { + @Autowired + private UEditorConfig uEditorConfig; + + @Autowired + private AwsProperty awsProperty; + @Autowired private RequestInterceptor requestInterceptor; + @Bean + @ConditionalOnMissingBean(ActionEnter.class) + public ActionEnter actionEnter() { + ActionEnter actionEnter = new ActionEnter(ConfigManager.getInstance(uEditorConfig, awsProperty)); + return actionEnter; + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.setAllowCredentials(true); + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + /** + * 用于处理编码问题 + * + * @return + */ + @Bean + public Filter characterEncodingFilter() { + CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); + characterEncodingFilter.setEncoding("UTF-8"); + characterEncodingFilter.setForceEncoding(true); + return characterEncodingFilter; + } + @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(requestInterceptor).addPathPatterns("/**"); @@ -35,6 +85,9 @@ public class WebConfig implements WebMvcConfigurer { .addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/"); + // ueditor + registry.addResourceHandler("/upload/**") + .addResourceLocations("file:" + uEditorConfig.getUploadPath()); //registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/"); } diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java new file mode 100644 index 000000000..b2eb2a842 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java @@ -0,0 +1,118 @@ +package com.iformall.ueditor; + +import com.iformall.ueditor.define.ActionMap; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import com.iformall.ueditor.hunter.FileManager; +import com.iformall.ueditor.hunter.ImageHunter; +import com.iformall.ueditor.upload.Uploader; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +public class ActionEnter { + + private HttpServletRequest request = null; + + private String actionType = null; + + private ConfigManager configManager = null; + + public ActionEnter(ConfigManager configManager) { + this.configManager = configManager; + } + + public String exec(HttpServletRequest request) { + this.request = request; + this.actionType = request.getParameter("action"); + String callbackName = this.request.getParameter("callback"); + + if (callbackName != null) { + + if (!validCallbackName(callbackName)) { + return new BaseState(false, AppInfo.ILLEGAL).toJSONString(); + } + + return callbackName + "(" + this.invoke() + ");"; + + } else { + return this.invoke(); + } + + } + + public String invoke() { + + if (actionType == null || !ActionMap.mapping.containsKey(actionType)) { + return new BaseState(false, AppInfo.INVALID_ACTION).toJSONString(); + } + + if (this.configManager == null || !this.configManager.valid()) { + return new BaseState(false, AppInfo.CONFIG_ERROR).toJSONString(); + } + + State state = null; + + int actionCode = ActionMap.getType(this.actionType); + + Map conf = null; + + switch (actionCode) { + + case ActionMap.CONFIG: + return this.configManager.getAllConfig().toString(); + + case ActionMap.UPLOAD_IMAGE: + case ActionMap.UPLOAD_SCRAWL: + case ActionMap.UPLOAD_VIDEO: + case ActionMap.UPLOAD_FILE: + conf = this.configManager.getConfig(actionCode); + state = new Uploader(request, conf).doExec(); + break; + + case ActionMap.CATCH_IMAGE: + conf = configManager.getConfig(actionCode); + String[] list = this.request.getParameterValues((String) conf.get("fieldName")); + state = new ImageHunter(conf).capture(list); + break; + + case ActionMap.LIST_IMAGE: + case ActionMap.LIST_FILE: + conf = configManager.getConfig(actionCode); + int start = this.getStartIndex(); + state = new FileManager(conf).listFile(start); + break; + + } + + return state.toJSONString(); + + } + + public int getStartIndex() { + + String start = this.request.getParameter("start"); + + try { + return Integer.parseInt(start); + } catch (Exception e) { + return 0; + } + + } + + /** + * callback参数验证 + */ + public boolean validCallbackName(String name) { + + if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) { + return true; + } + + return false; + + } + +} \ No newline at end of file diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java new file mode 100644 index 000000000..036c95c77 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java @@ -0,0 +1,223 @@ +package com.iformall.ueditor; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.iformall.config.AwsProperty; +import com.iformall.ueditor.define.ActionMap; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 配置管理器 + * + * @author hancong03@baidu.com + */ +public final class ConfigManager { + + private static final String configFileName = "config.json"; + private JSONObject jsonConfig = null; + // 涂鸦上传filename定义 + private final static String SCRAWL_FILE_NAME = "scrawl"; + // 远程图片抓取filename定义 + private final static String REMOTE_FILE_NAME = "remote"; + //配置信息 + private UEditorConfig uEditorConfig; + private AwsProperty awsProperty; + + /* + * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件 + */ + private ConfigManager(UEditorConfig uEditorConfig, AwsProperty awsProperty) throws IOException { + this.uEditorConfig = uEditorConfig; + this.awsProperty = awsProperty; + String configPath = uEditorConfig.getConfig(); + configPath = configPath == null || configPath.isEmpty() ? configFileName : configPath; + this.initEnv(configPath); + } + + /** + * 配置管理器构造工厂 + * + * @param uEditorConfig 配置文件 + * @return 配置管理器实例或者null + */ + public static ConfigManager getInstance(UEditorConfig uEditorConfig, AwsProperty awsProperty) { + + try { + return new ConfigManager(uEditorConfig, awsProperty); + } catch (Exception e) { + System.err.println("UEditor ConfigManager load error~"); + return null; + } + + } + + // 验证配置文件加载是否正确 + public boolean valid() { + return this.jsonConfig != null; + } + + public JSONObject getAllConfig() { + + return this.jsonConfig; + + } + + public Map getConfig(int type) { + + Map conf = new HashMap(); + String savePath = null; + + try { + switch (type) { + + case ActionMap.UPLOAD_FILE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("fileMaxSize")); + conf.put("allowFiles", this.getArray("fileAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("fileFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("filePathFormat"); + break; + + case ActionMap.UPLOAD_IMAGE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("imageMaxSize")); + conf.put("allowFiles", this.getArray("imageAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("imageFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("imagePathFormat"); + break; + + case ActionMap.UPLOAD_VIDEO: + conf.put("maxSize", this.jsonConfig.getLong("videoMaxSize")); + conf.put("allowFiles", this.getArray("videoAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("videoFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("videoPathFormat"); + break; + + case ActionMap.UPLOAD_SCRAWL: + conf.put("filename", ConfigManager.SCRAWL_FILE_NAME); + conf.put("maxSize", this.jsonConfig.getLong("scrawlMaxSize")); + conf.put("fieldName", this.jsonConfig.getString("scrawlFieldName")); + conf.put("isBase64", "true"); + savePath = this.jsonConfig.getString("scrawlPathFormat"); + break; + + case ActionMap.CATCH_IMAGE: + conf.put("filename", ConfigManager.REMOTE_FILE_NAME); + conf.put("filter", this.getArray("catcherLocalDomain")); + conf.put("maxSize", this.jsonConfig.getLong("catcherMaxSize")); + conf.put("allowFiles", this.getArray("catcherAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("catcherFieldName") + "[]"); + savePath = this.jsonConfig.getString("catcherPathFormat"); + break; + + case ActionMap.LIST_IMAGE: + conf.put("allowFiles", this.getArray("imageManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("imageManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("imageManagerListSize")); + break; + + case ActionMap.LIST_FILE: + conf.put("allowFiles", this.getArray("fileManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("fileManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("fileManagerListSize")); + break; + + } + } catch (JSONException e) { + e.printStackTrace(); + } + + conf.put("savePath", savePath); + conf.put("rootPath", uEditorConfig.getUploadPath()); + conf.put("urlPrefix", uEditorConfig.getUrlPrefix()); + return conf; + + } + + private void initEnv(String configPath) throws IOException { + + String configContent = this.readFile(configPath); + + try { + JSONObject jsonConfig = JSON.parseObject(configContent); + //统一url访问前缀 + if (uEditorConfig.getUnified()) { + Set> entrySet = jsonConfig.entrySet(); + for (Map.Entry entry : entrySet) { + String key = entry.getKey(); + if(key.contains("UrlPrefix")) { + jsonConfig.put(key, uEditorConfig.getUrlPrefix()); + } + } + } + this.jsonConfig = jsonConfig; + } catch (Exception e) { + this.jsonConfig = null; + } + + } + + private String[] getArray(String key) throws JSONException { + + JSONArray jsonArray = this.jsonConfig.getJSONArray(key); + String[] result = new String[jsonArray.size()]; + + for (int i = 0, len = jsonArray.size(); i < len; i++) { + result[i] = jsonArray.getString(i); + } + + return result; + + } + + private String readFile(String path) throws IOException { + + StringBuilder builder = new StringBuilder(); + + try { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path); + InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8"); + BufferedReader bfReader = new BufferedReader(reader); + + String tmpContent = null; + + while ((tmpContent = bfReader.readLine()) != null) { + builder.append(tmpContent); + } + + bfReader.close(); + + } catch (UnsupportedEncodingException e) { + // 忽略 + } + + return this.filter(builder.toString()); + + } + + // 过滤输入字符串, 剔除多行注释以及替换掉反斜杠 + private String filter(String input) { + + return input.replaceAll("/\\*[\\s\\S]*?\\*/", ""); + + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/Encoder.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/Encoder.java new file mode 100644 index 000000000..7ce810b43 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/Encoder.java @@ -0,0 +1,24 @@ +package com.iformall.ueditor; + +public class Encoder { + + public static String toUnicode ( String input ) { + + StringBuilder builder = new StringBuilder(); + char[] chars = input.toCharArray(); + + for ( char ch : chars ) { + + if ( ch < 256 ) { + builder.append( ch ); + } else { + builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) ); + } + + } + + return builder.toString(); + + } + +} \ No newline at end of file diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/PathFormat.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/PathFormat.java new file mode 100644 index 000000000..b388a2f2e --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/PathFormat.java @@ -0,0 +1,157 @@ +package com.iformall.ueditor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathFormat { + + private static final String TIME = "time"; + private static final String FULL_YEAR = "yyyy"; + private static final String YEAR = "yy"; + private static final String MONTH = "mm"; + private static final String DAY = "dd"; + private static final String HOUR = "hh"; + private static final String MINUTE = "ii"; + private static final String SECOND = "ss"; + private static final String RAND = "rand"; + + private static Date currentDate = null; + + public static String parse ( String input ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) ); + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + /** + * 格式化路径, 把windows路径替换成标准路径 + * @param input 待格式化的路径 + * @return 格式化后的路径 + */ + public static String format ( String input ) { + + return input.replace( "\\", "/" ); + + } + + public static String parse ( String input, String filename ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + String matchStr = null; + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matchStr = matcher.group( 1 ); + if ( matchStr.indexOf( "filename" ) != -1 ) { + filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" ); + matcher.appendReplacement(sb, filename ); + } else { + matcher.appendReplacement(sb, PathFormat.getString( matchStr ) ); + } + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + private static String getString ( String pattern ) { + + pattern = pattern.toLowerCase(); + + // time 处理 + if ( pattern.indexOf( PathFormat.TIME ) != -1 ) { + return PathFormat.getTimestamp(); + } else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) { + return PathFormat.getFullYear(); + } else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) { + return PathFormat.getYear(); + } else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) { + return PathFormat.getMonth(); + } else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) { + return PathFormat.getDay(); + } else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) { + return PathFormat.getHour(); + } else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) { + return PathFormat.getMinute(); + } else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) { + return PathFormat.getSecond(); + } else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) { + return PathFormat.getRandom( pattern ); + } + + return pattern; + + } + + private static String getTimestamp () { + return System.currentTimeMillis() + ""; + } + + private static String getFullYear () { + return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate ); + } + + private static String getYear () { + return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate ); + } + + private static String getMonth () { + return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate ); + } + + private static String getDay () { + return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate ); + } + + private static String getHour () { + return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate ); + } + + private static String getMinute () { + return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate ); + } + + private static String getSecond () { + return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate ); + } + + private static String getRandom ( String pattern ) { + + int length = 0; + pattern = pattern.split( ":" )[ 1 ].trim(); + + length = Integer.parseInt( pattern ); + + return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length ); + + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java new file mode 100644 index 000000000..8dcedbc4e --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java @@ -0,0 +1,59 @@ +package com.iformall.ueditor; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Created by pangxiaofeng on 2017/9/27. + */ +@ConfigurationProperties(prefix = "ueditor") +public class UEditorConfig { + + /** + * config.json的文件存放地址 + */ + private String config; + /** + * 是否同统一上传地址:图片上传地址,视频上传地址... + */ + private boolean unified; + /** + * 文件上传路径 + */ + private String uploadPath; + /** + * 文件url前缀 + */ + private String urlPrefix; + + public String getConfig() { + return config; + } + + public void setConfig(String config) { + this.config = config; + } + + public String getUploadPath() { + return uploadPath; + } + + public void setUploadPath(String uploadPath) { + this.uploadPath = uploadPath; + } + + public String getUrlPrefix() { + return urlPrefix; + } + + public void setUrlPrefix(String urlPrefix) { + this.urlPrefix = urlPrefix; + } + + public boolean getUnified() { + return unified; + } + + public void setUnified(boolean unified) { + this.unified = unified; + } +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java new file mode 100644 index 000000000..265425939 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java @@ -0,0 +1,42 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +/** + * 定义请求action类型 + * @author hancong03@baidu.com + * + */ +@SuppressWarnings("serial") +public final class ActionMap { + + public static final Map mapping; + // 获取配置请求 + public static final int CONFIG = 0; + public static final int UPLOAD_IMAGE = 1; + public static final int UPLOAD_SCRAWL = 2; + public static final int UPLOAD_VIDEO = 3; + public static final int UPLOAD_FILE = 4; + public static final int CATCH_IMAGE = 5; + public static final int LIST_FILE = 6; + public static final int LIST_IMAGE = 7; + + static { + mapping = new HashMap(){{ + put( "config", ActionMap.CONFIG ); + put( "uploadimage", ActionMap.UPLOAD_IMAGE ); + put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL ); + put( "uploadvideo", ActionMap.UPLOAD_VIDEO ); + put( "uploadfile", ActionMap.UPLOAD_FILE ); + put( "catchimage", ActionMap.CATCH_IMAGE ); + put( "listfile", ActionMap.LIST_FILE ); + put( "listimage", ActionMap.LIST_IMAGE ); + }}; + } + + public static int getType ( String key ) { + return ActionMap.mapping.get( key ); + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java new file mode 100644 index 000000000..bfbcf3d97 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java @@ -0,0 +1,5 @@ +package com.iformall.ueditor.define; + +public enum ActionState { + UNKNOW_ERROR +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java new file mode 100644 index 000000000..a31425d6f --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java @@ -0,0 +1,77 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public final class AppInfo { + + public static final int SUCCESS = 0; + public static final int MAX_SIZE = 1; + public static final int PERMISSION_DENIED = 2; + public static final int FAILED_CREATE_FILE = 3; + public static final int IO_ERROR = 4; + public static final int NOT_MULTIPART_CONTENT = 5; + public static final int PARSE_REQUEST_ERROR = 6; + public static final int NOTFOUND_UPLOAD_DATA = 7; + public static final int NOT_ALLOW_FILE_TYPE = 8; + + public static final int INVALID_ACTION = 101; + public static final int CONFIG_ERROR = 102; + + public static final int PREVENT_HOST = 201; + public static final int CONNECTION_ERROR = 202; + public static final int REMOTE_FAIL = 203; + + public static final int NOT_DIRECTORY = 301; + public static final int NOT_EXIST = 302; + + public static final int ILLEGAL = 401; + + public static Map info = new HashMap(){{ + + put( AppInfo.SUCCESS, "SUCCESS" ); + + // 无效的Action + put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" ); + // 配置文件初始化失败 + put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" ); + // 抓取远程图片失败 + put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" ); + + // 被阻止的远程主机 + put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" ); + // 远程连接出错 + put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" ); + + // "文件大小超出限制" + put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" ); + // 权限不足, 多指写权限 + put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" ); + // 创建文件失败 + put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" ); + // IO错误 + put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" ); + // 上传表单不是multipart/form-data类型 + put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" ); + // 解析上传表单错误 + put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" ); + // 未找到上传数据 + put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" ); + // 不允许的文件类型 + put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" ); + + // 指定路径不是目录 + put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" ); + // 指定路径并不存在 + put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" ); + + // callback参数名不合法 + put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" ); + + }}; + + public static String getStateInfo ( int key ) { + return AppInfo.info.get( key ); + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java new file mode 100644 index 000000000..db66dd2cc --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java @@ -0,0 +1,90 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class BaseState implements State { + + private boolean state = false; + private String info = null; + + private Map infoMap = new HashMap(); + + public BaseState () { + this.state = true; + } + + public BaseState ( boolean state ) { + this.setState( state ); + } + + public BaseState ( boolean state, String info ) { + this.setState( state ); + this.info = info; + } + + public BaseState ( boolean state, int infoCode ) { + this.setState( state ); + this.info = AppInfo.getStateInfo( infoCode ); + } + + public boolean isSuccess () { + return this.state; + } + + public void setState ( boolean state ) { + this.state = state; + } + + public void setInfo ( String info ) { + this.info = info; + } + + public void setInfo ( int infoCode ) { + this.info = AppInfo.getStateInfo( infoCode ); + } + + @Override + public String toJSONString() { + return this.toString(); + } + + public String toString () { + + String key = null; + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + Iterator iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + key = iterator.next(); + + builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" ); + + } + + builder.append( "}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public void putInfo(String name, long val) { + this.putInfo(name, val+""); + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/FileType.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/FileType.java new file mode 100644 index 000000000..ebc432554 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/FileType.java @@ -0,0 +1,31 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class FileType { + + public static final String JPG = "JPG"; + + private static final Map types = new HashMap(){{ + + put( FileType.JPG, ".jpg" ); + + }}; + + public static String getSuffix ( String key ) { + return FileType.types.get( key ); + } + + /** + * 根据给定的文件名,获取其后缀信息 + * @param filename + * @return + */ + public static String getSuffixByFilename ( String filename ) { + + return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase(); + + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java new file mode 100644 index 000000000..d76bb621c --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java @@ -0,0 +1,20 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class MIMEType { + + public static final Map types = new HashMap(){{ + put( "image/gif", ".gif" ); + put( "image/jpeg", ".jpg" ); + put( "image/jpg", ".jpg" ); + put( "image/png", ".png" ); + put( "image/bmp", ".bmp" ); + }}; + + public static String getSuffix ( String mime ) { + return MIMEType.types.get( mime ); + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java new file mode 100644 index 000000000..a1799cb2a --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java @@ -0,0 +1,108 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.*; + +/** + * 多状态集合状态 + * 其包含了多个状态的集合, 其本身自己也是一个状态 + * @author hancong03@baidu.com + * + */ +public class MultiState implements State { + + private boolean state = false; + private String info = null; + private Map intMap = new HashMap(); + private Map infoMap = new HashMap(); + private List stateList = new ArrayList(); + + public MultiState ( boolean state ) { + this.state = state; + } + + public MultiState ( boolean state, String info ) { + this.state = state; + this.info = info; + } + + public MultiState ( boolean state, int infoKey ) { + this.state = state; + this.info = AppInfo.getStateInfo( infoKey ); + } + + @Override + public boolean isSuccess() { + return this.state; + } + + public void addState ( State state ) { + stateList.add( state.toJSONString() ); + } + + /** + * 该方法调用无效果 + */ + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public String toJSONString() { + + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + // 数字转换 + Iterator iterator = this.intMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) ); + + } + + iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" ); + + } + + builder.append( ", list: [" ); + + + iterator = this.stateList.iterator(); + + while ( iterator.hasNext() ) { + + builder.append( iterator.next() + "," ); + + } + + if ( this.stateList.size() > 0 ) { + builder.deleteCharAt( builder.length() - 1 ); + } + + builder.append( " ]}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, long val) { + this.intMap.put( name, val ); + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/define/State.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/State.java new file mode 100644 index 000000000..1a8ca2d94 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/define/State.java @@ -0,0 +1,18 @@ +package com.iformall.ueditor.define; + +/** + * 处理状态接口 + * @author hancong03@baidu.com + * + */ +public interface State { + + public boolean isSuccess(); + + public void putInfo(String name, String val); + + public void putInfo(String name, long val); + + public String toJSONString(); + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java new file mode 100644 index 000000000..a21590d60 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java @@ -0,0 +1,111 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.MultiState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +public class FileManager { + + private String dir = null; + private String rootPath = null; + private String[] allowFiles = null; + private int count = 0; + + public FileManager(Map conf) { + + this.rootPath = (String) conf.get("rootPath"); + this.dir = this.rootPath + (String) conf.get("dir"); + this.allowFiles = this.getAllowFiles(conf.get("allowFiles")); + this.count = (Integer) conf.get("count"); + + } + + public State listFile(int index) { + + File dir = new File(this.dir); + State state = null; + + if (!dir.exists()) { + return new BaseState(false, AppInfo.NOT_EXIST); + } + + if (!dir.isDirectory()) { + return new BaseState(false, AppInfo.NOT_DIRECTORY); + } + + Collection list = FileUtils.listFiles(dir, this.allowFiles, true); + + if (index < 0 || index > list.size()) { + state = new MultiState(true); + } else { + Object[] fileList = Arrays.copyOfRange(list.toArray(), index, index + this.count); + state = this.getState(fileList); + } + + state.putInfo("start", index); + state.putInfo("total", list.size()); + + return state; + + } + + private State getState(Object[] files) { + + MultiState state = new MultiState(true); + BaseState fileState = null; + + File file = null; + + for (Object obj : files) { + if (obj == null) { + break; + } + file = (File) obj; + fileState = new BaseState(true); + fileState.putInfo("url", PathFormat.format(this.getPath(file))); + state.addState(fileState); + } + + return state; + + } + + private String getPath(File file) { + + String path = file.getAbsolutePath(); + path = PathFormat.format(path); + return path.replace(this.rootPath, "/"); + + } + + private String[] getAllowFiles(Object fileExt) { + + String[] exts = null; + String ext = null; + + if (fileExt == null) { + return new String[0]; + } + + exts = (String[]) fileExt; + + for (int i = 0, len = exts.length; i < len; i++) { + + ext = exts[i]; + exts[i] = ext.replace(".", ""); + + } + + return exts; + + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java new file mode 100644 index 000000000..1cd68ee62 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java @@ -0,0 +1,140 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.*; +import com.iformall.ueditor.upload.StorageManager; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 图片抓取器 + * @author hancong03@baidu.com + * + */ +public class ImageHunter { + + private String filename = null; + private String savePath = null; + private String rootPath = null; + private List allowTypes = null; + private long maxSize = -1; + + private List filters = null; + + public ImageHunter ( Map conf ) { + + this.filename = (String)conf.get( "filename" ); + this.savePath = (String)conf.get( "savePath" ); + this.rootPath = (String)conf.get( "rootPath" ); + this.maxSize = (Long)conf.get( "maxSize" ); + this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) ); + this.filters = Arrays.asList( (String[])conf.get( "filter" ) ); + + } + + public State capture (String[] list ) { + + MultiState state = new MultiState( true ); + + for ( String source : list ) { + state.addState( captureRemoteData( source ) ); + } + + return state; + + } + + public State captureRemoteData ( String urlStr ) { + + HttpURLConnection connection = null; + URL url = null; + String suffix = null; + + try { + url = new URL( urlStr ); + + if ( !validHost( url.getHost() ) ) { + return new BaseState( false, AppInfo.PREVENT_HOST ); + } + + connection = (HttpURLConnection) url.openConnection(); + + connection.setInstanceFollowRedirects( true ); + connection.setUseCaches( true ); + + if ( !validContentState( connection.getResponseCode() ) ) { + return new BaseState( false, AppInfo.CONNECTION_ERROR ); + } + + suffix = MIMEType.getSuffix( connection.getContentType() ); + + if ( !validFileType( suffix ) ) { + return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE ); + } + + if ( !validFileSize( connection.getContentLength() ) ) { + return new BaseState( false, AppInfo.MAX_SIZE ); + } + + String savePath = this.getPath( this.savePath, this.filename, suffix ); + String physicalPath = this.rootPath + savePath; + + State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath ); + + if ( state.isSuccess() ) { + state.putInfo( "url", PathFormat.format( savePath ) ); + state.putInfo( "source", urlStr ); + } + + return state; + + } catch ( Exception e ) { + return new BaseState( false, AppInfo.REMOTE_FAIL ); + } + + } + + private String getPath ( String savePath, String filename, String suffix ) { + + return PathFormat.parse( savePath + suffix, filename ); + + } + + private boolean validHost ( String hostname ) { + try { + InetAddress ip = InetAddress.getByName(hostname); + + if (ip.isSiteLocalAddress()) { + return false; + } + } catch (UnknownHostException e) { + return false; + } + + return !filters.contains( hostname ); + + } + + private boolean validContentState ( int code ) { + + return HttpURLConnection.HTTP_OK == code; + + } + + private boolean validFileType ( String type ) { + + return this.allowTypes.contains( type ); + + } + + private boolean validFileSize ( int size ) { + return size < this.maxSize; + } + +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java new file mode 100644 index 000000000..27b48b406 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java @@ -0,0 +1,51 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.codec.binary.Base64; + +import java.util.Map; + +public final class Base64Uploader { + + public static State save(String content, Map conf) { + + byte[] data = decode(content); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validSize(data, maxSize)) { + return new BaseState(false, AppInfo.MAX_SIZE); + } + + String suffix = FileType.getSuffix("JPG"); + + String savePath = PathFormat.parse((String) conf.get("savePath"), + (String) conf.get("filename")); + + savePath = savePath + suffix; + String physicalPath = (String) conf.get("rootPath") + savePath; + + State storageState = StorageManager.saveBinaryFile(data, physicalPath); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", ""); + } + + return storageState; + } + + private static byte[] decode(String content) { + return Base64.decodeBase64(content); + } + + private static boolean validSize(byte[] data, long length) { + return data.length <= length; + } + +} \ No newline at end of file diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java new file mode 100644 index 000000000..54e02de8e --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java @@ -0,0 +1,70 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class BinaryUploader { + + public static final State save(HttpServletRequest request, Map conf) { + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + MultipartFile file = ((MultipartHttpServletRequest) request).getFile("upfile"); + try { + if (file == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + + String savePath = (String) conf.get("savePath"); + String originFileName = file.getOriginalFilename(); + String suffix = FileType.getSuffixByFilename(file.getOriginalFilename()); + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + savePath = savePath + suffix; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, originFileName); + String physicalPath = (String) conf.get("rootPath") + savePath; + + InputStream is = file.getInputStream(); + State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("local", physicalPath); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + return storageState; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java new file mode 100644 index 000000000..ca0cdc65b --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java @@ -0,0 +1,148 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.*; + +public class StorageManager { + public static final int BUFFER_SIZE = 8192; + + public StorageManager() { + } + + public static State saveBinaryFile(byte[] data, String path) { + File file = new File(path); + + State state = valid(file); + + if (!state.isSuccess()) { + return state; + } + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bos.write(data); + bos.flush(); + bos.close(); + } catch (IOException ioe) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true, file.getAbsolutePath()); + state.putInfo("size", data.length); + state.putInfo("title", file.getName()); + return state; + } + + public static State saveFileByInputStream(InputStream is, String path, long maxSize) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + if (tmpFile.length() > maxSize) { + tmpFile.delete(); + return new BaseState(false, AppInfo.MAX_SIZE); + } + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + public static State saveFileByInputStream(InputStream is, String path) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static File getTmpFile() { + File tmpDir = FileUtils.getTempDirectory(); + String tmpFileName = (Math.random() * 10000 + "").replace(".", ""); + return new File(tmpDir, tmpFileName); + } + + private static State saveTmpFile(File tmpFile, String path) { + State state = null; + File targetFile = new File(path); + + if (targetFile.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + try { + FileUtils.moveFile(tmpFile, targetFile); + } catch (IOException e) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true); + state.putInfo("size", targetFile.length()); + state.putInfo("title", targetFile.getName()); + + return state; + } + + private static State valid(File file) { + File parentPath = file.getParentFile(); + + if ((!parentPath.exists()) && (!parentPath.mkdirs())) { + return new BaseState(false, AppInfo.FAILED_CREATE_FILE); + } + + if (!parentPath.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + + return new BaseState(true); + } +} diff --git a/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java new file mode 100644 index 000000000..aef29c651 --- /dev/null +++ b/mallinkAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java @@ -0,0 +1,110 @@ +package com.iformall.ueditor.upload; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.iformall.ueditor.define.State; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.UUID; + +public class Uploader { + + private HttpServletRequest request = null; + private Map conf = null; + + public Uploader(HttpServletRequest request, Map conf) { + this.request = request; + this.conf = conf; + } + + public final State doExec() { + String filedName = (String) this.conf.get("fieldName"); + State state = null; + + if ("true".equals(this.conf.get("isBase64"))) { + state = Base64Uploader.save(this.request.getParameter(filedName), + this.conf); + } else { + state = new BinaryUploader().save(this.request, this.conf); + + if (state.isSuccess()) { + JSONObject stateJson = JSON.parseObject(state.toJSONString()); + + MultipartFile multiReq= ((MultipartHttpServletRequest) this.request).getFile("upfile"); + String tenantId = "789"; //(String)SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multiReq.getContentType()); + metadata.setContentLength(multiReq.getSize()); + + try { + AmazonS3 s3 = AmazonS3ClientBuilder.standard() + .withRegion(conf.get("clientRegion").toString()) + .withCredentials(new AWSCredentialsProvider() { + @Override + public AWSCredentials getCredentials() { + return new BasicAWSCredentials(conf.get("access").toString(), conf.get("secret").toString()); + } + + @Override + public void refresh() { + + } + }) + .build(); + String fileName = UUID.randomUUID().toString(); + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + if (dot >= 0) { + fileName = tenantId + "/" + fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } else { + fileName = tenantId + "/" + fileName; + } + + + s3.putObject( + new PutObjectRequest(conf.get("bucketName").toString(), fileName, multiReq.getInputStream(), metadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + URL url = s3.getUrl(conf.get("bucketName").toString(), fileName); + //logger.info(url.toString()); + state.putInfo("url", url.toString()); + } catch (AmazonServiceException ase) { + /* + logger.warn("Caught an AmazonServiceException, which " + + "means your request made it " + + "to Amazon S3, but was rejected with an error response" + + " for some reason."); + logger.warn(ase.getMessage()); + */ + } catch (AmazonClientException ace) { + /* + logger.warn("Caught an AmazonClientException, which " + + "means the client encountered " + + "an internal error while trying to " + + "communicate with S3, " + + "such as not being able to access the network."); + logger.warn("Error Message: " + ace.getMessage()); + */ + } catch (IOException ioe) { + //logger.warn("Caught an IOException: " + ioe.getMessage()); + } + } + } + + return state; + } +} diff --git a/mallinkAdmin/src/main/resources/application.yml b/mallinkAdmin/src/main/resources/application.yml index 2587cdd4c..b6b981da6 100644 --- a/mallinkAdmin/src/main/resources/application.yml +++ b/mallinkAdmin/src/main/resources/application.yml @@ -67,6 +67,12 @@ aws: access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: http://localhost:9000/upload/ + wechat: open: componentAppId: "wx897e4673286c915d"