mxd 4 anni fa
parent
commit
6a59d0c510

+ 40 - 10
src/main/java/org/ssssssss/magicapi/adapter/Resource.java

@@ -1,64 +1,94 @@
 package org.ssssssss.magicapi.adapter;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
 import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 public interface Resource {
 
 	/**
 	 * 是否是只读
 	 */
-	default boolean readonly(){
+	default boolean readonly() {
 		return false;
 	}
 
 	/**
 	 * 是否存在
 	 */
-	default boolean exists(){
+	default boolean exists() {
 		return false;
 	}
 
 	/**
 	 * 是否是目录
 	 */
-	default boolean isDirectory(){
+	default boolean isDirectory() {
 		return false;
 	}
 
 	/**
 	 * 删除
 	 */
-	default boolean delete(){
+	default boolean delete() {
 		return false;
 	}
 
 	/**
 	 * 创建目录
 	 */
-	default boolean mkdir(){
+	default boolean mkdir() {
 		return false;
 	}
 
 	/**
 	 * 重命名
 	 */
-	default boolean renameTo(Resource resource){
+	default boolean renameTo(Resource resource) {
 		return false;
 	}
 
 	/**
 	 * 写入
 	 */
-	default boolean write(String content){
+	default boolean write(String content) {
 		return false;
 	}
+
 	/**
 	 * 写入
 	 */
-	default boolean write(byte[] bytes){
+	default boolean write(byte[] bytes) {
 		return false;
 	}
 
+	default void processExport(ZipOutputStream zos, String path, Resource directory, List<Resource> resources, List<String> excludes) throws IOException {
+		for (Resource resource : resources) {
+			if (resource.parent().getAbsolutePath().equals(directory.getAbsolutePath()) && !excludes.contains(resource.name())) {
+				if (resource.isDirectory()) {
+					String newPath = path + resource.name() + "/";
+					zos.putNextEntry(new ZipEntry(newPath));
+					zos.closeEntry();
+					processExport(zos, newPath, resource, resource.resources(), excludes);
+				} else {
+					System.out.println(path + resource.name());
+					zos.putNextEntry(new ZipEntry(path + resource.name()));
+					zos.write(resource.read());
+					zos.closeEntry();
+				}
+			}
+		}
+	}
+
+	default void export(OutputStream os, String... excludes) throws IOException {
+		ZipOutputStream zos = new ZipOutputStream(os);
+		processExport(zos, "", this, resources(), Arrays.asList(excludes == null ? new String[0] : excludes));
+		zos.close();
+	}
+
 	/**
 	 * 读取
 	 */
@@ -67,13 +97,13 @@ public interface Resource {
 	/**
 	 * 读取当前资源下的所有内容,主要是缓存作用。
 	 */
-	default void readAll(){
+	default void readAll() {
 	}
 
 	/**
 	 * 获取子目录
 	 */
-	default Resource getDirectory(String name){
+	default Resource getDirectory(String name) {
 		return getResource(name);
 	}
 

+ 1 - 0
src/main/java/org/ssssssss/magicapi/adapter/resource/FileResource.java

@@ -112,4 +112,5 @@ public class FileResource implements Resource {
 	public String toString() {
 		return String.format("file://%s", this.file.getAbsolutePath());
 	}
+
 }

+ 1 - 0
src/main/java/org/ssssssss/magicapi/adapter/resource/JarResource.java

@@ -124,4 +124,5 @@ public class JarResource implements Resource {
 	public String toString() {
 		return String.format("jar://%s", this.entryName);
 	}
+
 }

+ 35 - 6
src/main/java/org/ssssssss/magicapi/adapter/resource/KeyValueResource.java

@@ -2,10 +2,13 @@ package org.ssssssss.magicapi.adapter.resource;
 
 import org.ssssssss.magicapi.adapter.Resource;
 
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 public abstract class KeyValueResource implements Resource {
 
@@ -44,9 +47,9 @@ public abstract class KeyValueResource implements Resource {
 		// 判断移动的是否是文件夹
 		if (resource.isDirectory()) {
 			Set<String> oldKeys = this.keys();
-			Map<String,String> mappings = new HashMap<>(oldKeys.size());
+			Map<String, String> mappings = new HashMap<>(oldKeys.size());
 			int keyLen = this.path.length();
-			oldKeys.forEach(oldKey -> mappings.put(oldKey,targetResource.path + oldKey.substring(keyLen)));
+			oldKeys.forEach(oldKey -> mappings.put(oldKey, targetResource.path + oldKey.substring(keyLen)));
 			return renameTo(mappings);
 		} else {
 			return renameTo(Collections.singletonMap(this.path, targetResource.path));
@@ -58,7 +61,7 @@ public abstract class KeyValueResource implements Resource {
 		return this.keys().stream().allMatch(this::deleteByKey);
 	}
 
-	protected boolean deleteByKey(String key){
+	protected boolean deleteByKey(String key) {
 		return false;
 	}
 
@@ -70,8 +73,8 @@ public abstract class KeyValueResource implements Resource {
 	@Override
 	public String name() {
 		String name = this.path;
-		if(isDirectory()){
-			name = this.path.substring(0,name.length() - 1);
+		if (isDirectory()) {
+			name = this.path.substring(0, name.length() - 1);
 		}
 		int index = name.lastIndexOf(separator);
 		return index > -1 ? name.substring(index + 1) : name;
@@ -90,7 +93,7 @@ public abstract class KeyValueResource implements Resource {
 
 	@Override
 	public boolean mkdir() {
-		if(!isDirectory()){
+		if (!isDirectory()) {
 			this.path += separator;
 		}
 		return write("this is directory");
@@ -129,4 +132,30 @@ public abstract class KeyValueResource implements Resource {
 	public String getAbsolutePath() {
 		return this.path;
 	}
+
+	@Override
+	public void processExport(ZipOutputStream zos, String path, Resource directory, List<Resource> resources, List<String> excludes) throws IOException {
+		for (Resource resource : resources) {
+			String fullName = directory.getAbsolutePath();
+			if (!fullName.endsWith(separator)) {
+				fullName += separator;
+			}
+			fullName += resource.name();
+			if (resource.isDirectory()) {
+				fullName += separator;
+			}
+			if (fullName.equals(resource.getAbsolutePath()) && !excludes.contains(resource.name())) {
+				if (resource.isDirectory()) {
+					String newPath = path + resource.name() + "/";
+					zos.putNextEntry(new ZipEntry(newPath));
+					zos.closeEntry();
+					processExport(zos, newPath, resource, resources, excludes);
+				} else {
+					zos.putNextEntry(new ZipEntry(path + resource.name()));
+					zos.write(resource.read());
+					zos.closeEntry();
+				}
+			}
+		}
+	}
 }

+ 6 - 0
src/main/java/org/ssssssss/magicapi/controller/MagicController.java

@@ -60,6 +60,12 @@ public class MagicController implements JsonCodeConstants {
 		}
 	}
 
+	public void notNull(Object value, JsonCode jsonCode) {
+		if (value == null) {
+			throw new InvalidArgumentException(jsonCode);
+		}
+	}
+
 	public void isTrue(boolean value, JsonCode jsonCode) {
 		if (!value) {
 			throw new InvalidArgumentException(jsonCode);

+ 1 - 1
src/main/java/org/ssssssss/magicapi/controller/MagicGroupController.java

@@ -36,7 +36,7 @@ public class MagicGroupController extends MagicController {
 		TreeNode<Group> treeNode = configuration.getGroupServiceProvider().apiGroupTree().findTreeNode(group -> group.getId().equals(groupId));
 		if (treeNode == null) {
 			treeNode = configuration.getGroupServiceProvider().functionGroupTree().findTreeNode(group -> group.getId().equals(groupId));
-			isTrue(treeNode != null, GROUP_NOT_FOUND);
+			notNull(treeNode, GROUP_NOT_FOUND);
 			isApi = false;
 		}
 		List<String> children = treeNode.flat().stream().map(Group::getId).collect(Collectors.toList());

+ 26 - 0
src/main/java/org/ssssssss/magicapi/controller/MagicWorkbenchController.java

@@ -1,20 +1,27 @@
 package org.ssssssss.magicapi.controller;
 
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
 import org.springframework.util.ResourceUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+import org.ssssssss.magicapi.adapter.Resource;
 import org.ssssssss.magicapi.config.MagicConfiguration;
+import org.ssssssss.magicapi.config.Valid;
+import org.ssssssss.magicapi.interceptor.RequestInterceptor;
 import org.ssssssss.magicapi.logging.MagicLoggerContext;
 import org.ssssssss.magicapi.model.JsonBean;
 import org.ssssssss.magicapi.model.Options;
+import org.ssssssss.magicapi.modules.ResponseModule;
 import org.ssssssss.magicapi.utils.MD5Utils;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -78,4 +85,23 @@ public class MagicWorkbenchController extends MagicController {
 		}
 		return "var MAGIC_EDITOR_CONFIG = {}";
 	}
+
+	@RequestMapping("/download")
+	@Valid(authorization = RequestInterceptor.Authorization.DOWNLOAD)
+	@ResponseBody
+	public ResponseEntity<?> download(String groupId) throws IOException {
+		if (StringUtils.isBlank(groupId)) {
+			return download(configuration.getWorkspace(), "magic-api-all.zip");
+		} else {
+			Resource resource = configuration.getGroupServiceProvider().getGroupResource(groupId);
+			notNull(resource, GROUP_NOT_FOUND);
+			return download(resource, "magic-api-group.zip");
+		}
+	}
+
+	private ResponseEntity<?> download(Resource resource, String filename) throws IOException {
+		ByteArrayOutputStream os = new ByteArrayOutputStream();
+		resource.export(os,"backups");
+		return ResponseModule.download(os.toByteArray(),filename);
+	}
 }

+ 1 - 1
src/main/java/org/ssssssss/magicapi/interceptor/RequestInterceptor.java

@@ -13,7 +13,7 @@ import javax.servlet.http.HttpServletResponse;
 public interface RequestInterceptor {
 
 	enum Authorization {
-		NONE, SAVE, DETAIL, RUN, DELETE
+		NONE, SAVE, DETAIL, RUN, DELETE, DOWNLOAD, UPLOAD
 	}
 
 	/**

+ 1 - 1
src/main/java/org/ssssssss/magicapi/modules/ResponseModule.java

@@ -188,7 +188,7 @@ public class ResponseModule {
 	 * @param filename 文件名
 	 */
 	@Comment("文件下载")
-	public ResponseEntity download(@Comment("文件内容,如`byte[]`") Object value, @Comment("文件名") String filename) throws UnsupportedEncodingException {
+	public static ResponseEntity<?> download(@Comment("文件内容,如`byte[]`") Object value, @Comment("文件名") String filename) throws UnsupportedEncodingException {
 		return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)
 				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(filename, "UTF-8"))
 				.body(value);