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"