diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md index 7255cc35..525d8be4 100644 --- a/doc/docs/_sidebar.md +++ b/doc/docs/_sidebar.md @@ -1,26 +1,26 @@ -* [首页](/?t=1557743036163) +* [首页](/?t=1557833057337) * 开发文档 - * [快速体验](files/10010_快速体验.md?t=1557743036167) - * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1557743036187) - * [新增接口](files/10020_新增接口.md?t=1557743036187) - * [业务参数校验](files/10030_业务参数校验.md?t=1557743036187) - * [错误处理](files/10040_错误处理.md?t=1557743036187) - * [编写文档](files/10041_编写文档.md?t=1557743036188) - * [接口交互详解](files/10050_接口交互详解.md?t=1557743036188) - * [easyopen支持](files/10070_easyopen支持.md?t=1557743036188) - * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1557743036188) - * [ISV管理](files/10085_ISV管理.md?t=1557743036188) - * [路由授权](files/10090_路由授权.md?t=1557743036188) - * [接口限流](files/10092_接口限流.md?t=1557743036188) - * [SDK开发](files/10095_SDK开发.md?t=1557743036189) - * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1557743036189) - * [应用授权](files/10097_应用授权.md?t=1557743036189) - * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1557743036189) - * [对接前端](files/10100_对接前端.md?t=1557743036189) - * [自定义过滤器](files/10102_自定义过滤器.md?t=1557743036189) + * [快速体验](files/10010_快速体验.md?t=1557833057339) + * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1557833057355) + * [新增接口](files/10020_新增接口.md?t=1557833057355) + * [业务参数校验](files/10030_业务参数校验.md?t=1557833057355) + * [错误处理](files/10040_错误处理.md?t=1557833057355) + * [编写文档](files/10041_编写文档.md?t=1557833057355) + * [接口交互详解](files/10050_接口交互详解.md?t=1557833057355) + * [easyopen支持](files/10070_easyopen支持.md?t=1557833057356) + * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1557833057356) + * [ISV管理](files/10085_ISV管理.md?t=1557833057356) + * [路由授权](files/10090_路由授权.md?t=1557833057356) + * [接口限流](files/10092_接口限流.md?t=1557833057356) + * [SDK开发](files/10095_SDK开发.md?t=1557833057356) + * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1557833057356) + * [应用授权](files/10097_应用授权.md?t=1557833057356) + * [更改数据节点名称](files/10099_更改数据节点名称.md?t=1557833057356) + * [对接前端](files/10100_对接前端.md?t=1557833057356) + * [自定义过滤器](files/10102_自定义过滤器.md?t=1557833057356) * 原理分析 - * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1557743036189) - * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1557743036190) - * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1557743036190) - * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1557743036190) - * [常见问题](files/90100_常见问题.md?t=1557743036190) + * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1557833057357) + * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1557833057357) + * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1557833057357) + * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1557833057357) + * [常见问题](files/90100_常见问题.md?t=1557833057357) diff --git a/doc/docs/files/10102_自定义过滤器.md b/doc/docs/files/10102_自定义过滤器.md index 867bec64..3b53e445 100644 --- a/doc/docs/files/10102_自定义过滤器.md +++ b/doc/docs/files/10102_自定义过滤器.md @@ -11,7 +11,7 @@ zuul过滤器列表如下: | pre | -998 | PreLimitFilter (SOP自带) | 限流拦截器 | | pre | -3 | ServletDetectionFilter | 标记处理 Servlet 的类型 | | pre | -2 | Servlet30WrapperFilter | 包装 HttpServletRequest 请求 | -| pre | -1 | FormBodyWrapperFilter | 包装请求体 | +| pre | -1 | FormBodyWrapperFilter | 包装请求体 Servlet30WrapperFilter | | pre | 1 | DebugFilter | 标记调试标志 | | pre | 5 | PreDecorationFilter | 决定路由转发过滤器 | | route | 10 | RibbonRoutingFilter | serviceId 请求转发 | diff --git a/sop-common/pom.xml b/sop-common/pom.xml index 369bf561..e7ff103c 100644 --- a/sop-common/pom.xml +++ b/sop-common/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.gitee.sop sop-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT pom diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml index dc64ecc9..857aef07 100644 --- a/sop-common/sop-gateway-common/pom.xml +++ b/sop-common/sop-gateway-common/pom.xml @@ -5,11 +5,11 @@ com.gitee.sop sop-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT ../pom.xml sop-gateway-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT jar sop-gateway-common diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java index 68da9b72..f4bfc39c 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/BaseParamBuilder.java @@ -34,6 +34,9 @@ public abstract class BaseParamBuilder implements ParamBuilder { } protected void initOtherProperty(ApiParam apiParam) { + if (apiParam.size() == 0) { + throw ErrorEnum.ISV_INVALID_METHOD.getErrorMeta().getException(); + } RouteRepository routeRepository = RouteRepositoryContext.getRouteRepository(); if (routeRepository == null) { log.error("RouteRepositoryContext.setRouteRepository()方法未使用"); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java index 6c44e6b6..b157949b 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java @@ -1,7 +1,12 @@ package com.gitee.sop.gatewaycommon.util; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @@ -9,6 +14,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Collections; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -18,7 +25,12 @@ import java.util.Set; */ public class RequestUtil { - private RequestUtil(){} + private static Logger log = LoggerFactory.getLogger(RequestUtil.class); + + private RequestUtil() { + } + + public static final String MULTIPART = "multipart/"; private static final String UTF8 = "UTF-8"; @@ -57,7 +69,7 @@ public class RequestUtil { */ public static Map convertRequestParamsToMap(HttpServletRequest request) { Map paramMap = request.getParameterMap(); - if(paramMap == null || paramMap.isEmpty()) { + if (paramMap == null || paramMap.isEmpty()) { return Collections.emptyMap(); } Map retMap = new HashMap<>(paramMap.size()); @@ -76,6 +88,40 @@ public class RequestUtil { return retMap; } + /** + * 获取文件上传表单中的字段,不包括文件,请求类型是multipart/form-data + * + * @param request + * @return 返回表单中的字段内容 + */ + public static Map convertMultipartRequestToMap(HttpServletRequest request) { + DiskFileItemFactory factory = new DiskFileItemFactory(); + //2、创建一个文件上传解析器 + ServletFileUpload upload = new ServletFileUpload(factory); + Map params = new HashMap<>(); + try { + List fileItems = upload.parseRequest(request); + for (FileItem fileItem : fileItems) { + if (fileItem.isFormField()) { + params.put(fileItem.getFieldName(), fileItem.getString(UTF8)); + } + } + } catch (Exception e) { + log.error("参数解析错误", e); + } + return params; + } + + public static boolean isMultipart(HttpServletRequest request) { + String contentType = request.getContentType(); + // Don't use this filter on GET method + if (contentType == null) { + return false; + } + return contentType.toLowerCase(Locale.ENGLISH).startsWith(MULTIPART); + } + + public static String getText(HttpServletRequest request) throws IOException { return IOUtils.toString(request.getInputStream(), UTF8); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java index 45d17017..051d1a5d 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java @@ -4,10 +4,12 @@ import com.gitee.sop.gatewaycommon.bean.ApiContext; import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration; import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext; import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter; +import com.gitee.sop.gatewaycommon.zuul.filter.FormBodyWrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.filter.PostResultFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreLimitFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreRoutePermissionFilter; import com.gitee.sop.gatewaycommon.zuul.filter.PreValidateFilter; +import com.gitee.sop.gatewaycommon.zuul.filter.Servlet30WrapperFilterExt; import com.gitee.sop.gatewaycommon.zuul.route.SopRouteLocator; import com.gitee.sop.gatewaycommon.zuul.route.ZuulRouteRepository; import com.gitee.sop.gatewaycommon.zuul.route.ZuulZookeeperRouteManager; @@ -42,6 +44,16 @@ public class BaseZuulConfiguration extends AbstractConfiguration { return zuulRouteRepository; } + @Bean + FormBodyWrapperFilterExt formBodyWrapperFilterExt() { + return new FormBodyWrapperFilterExt(); + } + + @Bean + Servlet30WrapperFilterExt servlet30WrapperFilterExt() { + return new Servlet30WrapperFilterExt(); + } + /** * 选取路由 * @param zuulRouteRepository diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/FormBodyWrapperFilterExt.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/FormBodyWrapperFilterExt.java new file mode 100644 index 00000000..54987a19 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/FormBodyWrapperFilterExt.java @@ -0,0 +1,22 @@ +package com.gitee.sop.gatewaycommon.zuul.filter; + +import com.gitee.sop.gatewaycommon.util.RequestUtil; +import com.netflix.zuul.context.RequestContext; +import org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author tanghc + */ +public class FormBodyWrapperFilterExt extends FormBodyWrapperFilter { + + + @Override + public boolean shouldFilter() { + RequestContext ctx = RequestContext.getCurrentContext(); + HttpServletRequest request = ctx.getRequest(); + // 不是上传文件请求,则进行包装 + return !RequestUtil.isMultipart(request); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/Servlet30WrapperFilterExt.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/Servlet30WrapperFilterExt.java new file mode 100644 index 00000000..dac29699 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/Servlet30WrapperFilterExt.java @@ -0,0 +1,20 @@ +package com.gitee.sop.gatewaycommon.zuul.filter; + +import com.gitee.sop.gatewaycommon.util.RequestUtil; +import com.netflix.zuul.context.RequestContext; +import org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author tanghc + */ +public class Servlet30WrapperFilterExt extends Servlet30WrapperFilter { + @Override + public boolean shouldFilter() { + RequestContext ctx = RequestContext.getCurrentContext(); + HttpServletRequest request = ctx.getRequest(); + // 不是上传文件请求,则进行包装 + return !RequestUtil.isMultipart(request); + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java index b2e60b5a..28bb7ec3 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParamBuilder.java @@ -6,10 +6,16 @@ import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.BaseParamBuilder; import com.gitee.sop.gatewaycommon.util.RequestUtil; import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.http.HttpServletRequestWrapper; +import com.netflix.zuul.http.ServletInputStreamWrapper; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.io.IOUtils; import org.springframework.http.MediaType; +import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; +import java.io.IOException; import java.util.Map; /** @@ -24,7 +30,6 @@ public class ZuulParamBuilder extends BaseParamBuilder { private static final String CONTENT_TYPE_TEXT = MediaType.TEXT_PLAIN_VALUE; private static final String GET = "get"; - @Override public Map buildRequestParams(RequestContext ctx) { HttpServletRequest request = ctx.getRequest(); @@ -44,6 +49,11 @@ public class ZuulParamBuilder extends BaseParamBuilder { // json或者纯文本形式 if (contentType.contains(CONTENT_TYPE_JSON) || contentType.contains(CONTENT_TYPE_TEXT)) { throw ErrorEnum.ISV_INVALID_CONTENT_TYPE.getErrorMeta().getException(); + } else if (ServletFileUpload.isMultipartContent(request)) { + MultipartRequestWrapper wrapper = new MultipartRequestWrapper(request); + ctx.setRequest(wrapper); + ctx.getZuulRequestHeaders().put("content-type", wrapper.getContentType()); + params = RequestUtil.convertMultipartRequestToMap(wrapper); } else { params = RequestUtil.convertRequestParamsToMap(request); } @@ -63,4 +73,45 @@ public class ZuulParamBuilder extends BaseParamBuilder { return apiParam; } + public static class MultipartRequestWrapper extends HttpServletRequestWrapper { + private HttpServletRequest request; + + private volatile byte[] contentData; + + private MediaType contentType; + + private int contentLength; + + public MultipartRequestWrapper(HttpServletRequest request) { + super(request); + this.request = request; + try { + this.contentType = MediaType.valueOf(this.request.getContentType()); + byte[] input = IOUtils.toByteArray(request.getInputStream()); + this.contentData = input; + this.contentLength = input.length; + } catch (Exception e) { + throw new IllegalStateException("Cannot convert form data", e); + } + } + + @Override + public String getContentType() { + return this.contentType.toString(); + } + + @Override + public int getContentLength() { + if (super.getContentLength() <= 0) { + return super.getContentLength(); + } + return this.contentLength; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new ServletInputStreamWrapper(this.contentData); + } + } + } diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml index e5e0df9b..b159d7b7 100644 --- a/sop-common/sop-service-common/pom.xml +++ b/sop-common/sop-service-common/pom.xml @@ -6,11 +6,11 @@ com.gitee.sop sop-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT ../pom.xml sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT jar sop-service-common diff --git a/sop-example/sop-auth/pom.xml b/sop-example/sop-auth/pom.xml index e058e224..cfb9b7ac 100644 --- a/sop-example/sop-auth/pom.xml +++ b/sop-example/sop-auth/pom.xml @@ -26,7 +26,7 @@ com.gitee.sop sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT org.springframework.cloud diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml index 3da24db7..5de15677 100644 --- a/sop-example/sop-book/sop-book-web/pom.xml +++ b/sop-example/sop-book/sop-book-web/pom.xml @@ -23,7 +23,7 @@ com.gitee.sop sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml index cb0317c3..2f255227 100644 --- a/sop-example/sop-easyopen/pom.xml +++ b/sop-example/sop-easyopen/pom.xml @@ -29,7 +29,7 @@ com.gitee.sop sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT org.springframework.cloud diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml index e3f77e7a..151c5126 100644 --- a/sop-example/sop-springmvc/pom.xml +++ b/sop-example/sop-springmvc/pom.xml @@ -20,7 +20,7 @@ com.gitee.sop sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml index 3fc61562..0c6eb075 100644 --- a/sop-example/sop-story/sop-story-web/pom.xml +++ b/sop-example/sop-story/sop-story-web/pom.xml @@ -23,7 +23,7 @@ com.gitee.sop sop-service-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT com.gitee.sop diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java new file mode 100644 index 00000000..6510fa74 --- /dev/null +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java @@ -0,0 +1,56 @@ +package com.gitee.sop.storyweb.controller; + +import com.gitee.sop.servercommon.annotation.ApiMapping; +import com.gitee.sop.storyweb.controller.param.FileUploadParam; +import com.gitee.sop.storyweb.vo.FileUploadVO; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.io.IOUtils; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Map; + +/** + * 演示文件上传 + * @author tanghc + */ +@RestController +public class FileUploadDemoController { + + /** + * 接收客户端上传的文件,然后把文件信息返回给客户端 + * @param param + * @param request + * @return + */ + @ApiMapping(value = "demo.file.upload", ignoreValidate = true) + public FileUploadVO file(FileUploadParam param, HttpServletRequest request) { + System.out.println(param.getRemark()); + FileUploadVO vo = new FileUploadVO(); + //检查form中是否有enctype="multipart/form-data" + if (ServletFileUpload.isMultipartContent(request)) { + //将request变成多部分request + MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; + Map fileMap = multiRequest.getFileMap(); + fileMap.entrySet() + .stream() + .forEach(entry->{ + MultipartFile multipartFile = entry.getValue(); + try { + String fileName = multipartFile.getOriginalFilename(); + long size = multipartFile.getSize(); + String fileContent = IOUtils.toString(multipartFile.getInputStream(), "UTF-8"); + FileUploadVO.FileMeta fileMeta = new FileUploadVO.FileMeta(fileName, size, fileContent); + vo.getFiles().add(fileMeta); + System.out.println(fileContent); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + return vo; + } +} diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/param/FileUploadParam.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/param/FileUploadParam.java new file mode 100644 index 00000000..ed29e119 --- /dev/null +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/param/FileUploadParam.java @@ -0,0 +1,11 @@ +package com.gitee.sop.storyweb.controller.param; + +import lombok.Data; + +/** + * @author tanghc + */ +@Data +public class FileUploadParam { + private String remark; +} diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/vo/FileUploadVO.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/vo/FileUploadVO.java new file mode 100644 index 00000000..6367cb08 --- /dev/null +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/vo/FileUploadVO.java @@ -0,0 +1,32 @@ +package com.gitee.sop.storyweb.vo; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author tanghc + */ +@Data +public class FileUploadVO { + + private List files = new ArrayList(); + + @Data + public static class FileMeta { + + public FileMeta(String filename, long size, String content) { + this.filename = filename; + this.size = size; + this.content = content; + } + + public FileMeta() { + } + + private String filename; + private long size; + private String content; + } +} diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml index 54419db9..be666783 100644 --- a/sop-gateway/pom.xml +++ b/sop-gateway/pom.xml @@ -23,7 +23,7 @@ com.gitee.sop sop-gateway-common - 1.7.2-SNAPSHOT + 1.8.0-SNAPSHOT diff --git a/sop-gateway/src/main/resources/application-dev.yml b/sop-gateway/src/main/resources/application-dev.yml index db470bbe..789eb0a4 100644 --- a/sop-gateway/src/main/resources/application-dev.yml +++ b/sop-gateway/src/main/resources/application-dev.yml @@ -4,8 +4,15 @@ server: zuul: # 入口地址,不用改,默认是/zuul servlet-path: /api + # 禁用默认的过滤器,不能删,不用改 + FormBodyWrapperFilter: + pre: + disable: true + Servlet30WrapperFilter: + pre: + disable: true -# 注册中心 +# 注册中心,根据实际情况修改 eureka: serverAddr: localhost:1111 client: @@ -15,21 +22,29 @@ eureka: spring: application: name: api-gateway - + # zookeeper,根据实际情况修改 cloud: zookeeper: connect-string: localhost:2181 - gateway: # Spring Cloud Gateway配置,如果用了zuul,这段配置没有效果 + # Spring Cloud Gateway配置,如果用了zuul,这段配置没有效果,不用改 + gateway: discovery: locator: lower-case-service-id: true enabled: true - # 数据源 + # 数据源,根据实际情况修改 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/sop?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull username: root - password: root \ No newline at end of file + password: root + + # 上传文件配置,根据实际情况修改 + servlet: + multipart: + enabled: true + max-file-size: 20MB # 上传文件最大20MB,默认1MB + max-request-size: 20MB diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenClient.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenClient.java index 076b396e..43d5e62c 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenClient.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenClient.java @@ -25,6 +25,7 @@ public class OpenClient { private static final Log log = LogFactory.getLog(OpenClient.class); private static final OpenConfig DEFAULT_CONFIG = new OpenConfig(); + public static final String ERROR_RESPONSE_KEY = "error_response"; private String url; private String appId; @@ -110,6 +111,10 @@ public class OpenClient { String method = request.getMethod(); String dataName = dataNameBuilder.build(method); JSONObject jsonObject = JSON.parseObject(resp); + boolean errorResponse = jsonObject.containsKey(ERROR_RESPONSE_KEY); + if (errorResponse) { + dataName = ERROR_RESPONSE_KEY; + } JSONObject data = jsonObject.getJSONObject(dataName); T t = data.toJavaObject(request.getResponseClass()); t.setBody(data.toJSONString()); diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenHttp.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenHttp.java index f5d1b4ef..46dc0153 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenHttp.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenHttp.java @@ -6,7 +6,6 @@ import okhttp3.Cookie; import okhttp3.CookieJar; import okhttp3.FormBody; import okhttp3.HttpUrl; -import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -26,8 +25,6 @@ import java.util.concurrent.TimeUnit; * @author tanghc */ public class OpenHttp { - public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - private Map> cookieStore = new HashMap>(); private OkHttpClient httpClient; diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/UploadFile.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/UploadFile.java index b616593b..c44e8e3d 100644 --- a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/UploadFile.java +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/common/UploadFile.java @@ -3,6 +3,8 @@ package com.gitee.sop.sdk.common; import com.gitee.sop.sdk.util.FileUtil; import com.gitee.sop.sdk.util.MD5Util; +import lombok.Getter; +import lombok.Setter; import java.io.File; import java.io.IOException; @@ -13,6 +15,8 @@ import java.io.Serializable; * 文件上传类 * @author tanghc */ +@Getter +@Setter public class UploadFile implements Serializable { private static final long serialVersionUID = -1100614660944996398L; @@ -53,36 +57,4 @@ public class UploadFile implements Serializable { private byte[] fileData; private String md5; - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public byte[] getFileData() { - return fileData; - } - - public void setFileData(byte[] fileData) { - this.fileData = fileData; - } - - public String getMd5() { - return md5; - } - - public void setMd5(String md5) { - this.md5 = md5; - } - } diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/model/DemoFileUploadModel.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/model/DemoFileUploadModel.java new file mode 100644 index 00000000..d0dea502 --- /dev/null +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/model/DemoFileUploadModel.java @@ -0,0 +1,11 @@ +package com.gitee.sop.sdk.model; + +import lombok.Data; + +/** + * @author tanghc + */ +@Data +public class DemoFileUploadModel { + private String remark; +} diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/request/DemoFileUploadRequest.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/request/DemoFileUploadRequest.java new file mode 100644 index 00000000..b5b6c340 --- /dev/null +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/request/DemoFileUploadRequest.java @@ -0,0 +1,13 @@ +package com.gitee.sop.sdk.request; + +import com.gitee.sop.sdk.response.DemoFileUploadResponse; + +/** + * @author tanghc + */ +public class DemoFileUploadRequest extends BaseRequest { + @Override + protected String method() { + return "demo.file.upload"; + } +} diff --git a/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/DemoFileUploadResponse.java b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/DemoFileUploadResponse.java new file mode 100644 index 00000000..e981acca --- /dev/null +++ b/sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/response/DemoFileUploadResponse.java @@ -0,0 +1,34 @@ +package com.gitee.sop.sdk.response; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author tanghc + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class DemoFileUploadResponse extends BaseResponse { + + private List files = new ArrayList(); + + @Data + public static class FileMeta { + + public FileMeta(String filename, long size, String content) { + this.filename = filename; + this.size = size; + this.content = content; + } + + public FileMeta() { + } + + private String filename; + private long size; + private String content; + } +} diff --git a/sop-sdk/sdk-java/src/main/resources/file1.txt b/sop-sdk/sdk-java/src/main/resources/file1.txt new file mode 100644 index 00000000..2e80f50e --- /dev/null +++ b/sop-sdk/sdk-java/src/main/resources/file1.txt @@ -0,0 +1 @@ +file1 content \ No newline at end of file diff --git a/sop-sdk/sdk-java/src/main/resources/file2.txt b/sop-sdk/sdk-java/src/main/resources/file2.txt new file mode 100644 index 00000000..ef01a4a0 --- /dev/null +++ b/sop-sdk/sdk-java/src/main/resources/file2.txt @@ -0,0 +1 @@ +file2 content... \ No newline at end of file diff --git a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/1.txt b/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/1.txt deleted file mode 100644 index 14684f6b..00000000 --- a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/1.txt +++ /dev/null @@ -1,2 +0,0 @@ -回忆起 20多年来我们一起走过的日子,我就感到特别温馨、特别甜蜜。你第一次闯入我生命中的情景,仿佛就在眼前……第一次偶然相遇是1996年5月,那是一个夏风习习的夜晚,我刚从工地回来,同事就邀我一起去城建学院跳舞,踏进舞厅的一瞬间,在暗淡温柔的霓虹灯下,你那清新脱俗的靓影一下子就深深的嵌入了我的心里。 -记得大学时代,李春波的歌曲“小芳”响彻校园,那个叫小芳的村里姑娘,也深深的烙进了我的心底,成了我少年时的梦中偶像。二十多年来,我一直期盼着找到一个象歌曲中所唱的长得好看又善良、有着一双美丽的大眼睛和两条粗辫子的姑娘做我的爱人,但苦苦寻觅却难见芳踪,谁知众里寻她千百度,蓦然回首,那人却在灯火阑珊处……你就这样俏生生的突然出现在我眼前。当时,你穿着浅绿色的衬衣,正在与一位女同学翩翩起舞,两条又粗又长的辫子在身后灵巧的晃动。一曲终了,我急忙挤到你身边请你跳舞。当时的我还不太会跳舞,还好是一首慢四舞曲,我才没出洋相。拥着你在舞厅漫步,因为心情特别激动,又怕舞步不熟踩到你脚,我眼睛始终盯着脚下,不敢正视你的目光;好不容易平复心情与你搭讪,才打探到你是教育学院的学生舞曲就结束了。后面的舞曲不是我不会跳就是被你那“讨厌”的女同学捷足先登了,始终没有机会再次与你共舞,但我的心已经完完全全的被你牵走了。同事周云看我不再跳舞、心事重重的,就问我为什么,得知我心事后,自告奋勇的说下一曲他去邀请你同学,让我有机会请你跳舞。可没想到我那同事的“光头”会把你们吓跑,让上天给我们安排的第一次相遇就这样擦肩而过。 \ No newline at end of file diff --git a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/2.txt b/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/2.txt deleted file mode 100644 index 63d15603..00000000 --- a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/2.txt +++ /dev/null @@ -1 +0,0 @@ -红与青 时光如流水般,在我面前一闪而过,但我却只能暗暗叹息。 台灯下,小桌前,我坐在那儿,目光停在桌子上的那一个西瓜面前。十几年前的往事仿佛就在昨日。 小时候,我们兄弟几个围坐在一张破破的桌子前。一个勺子,半个西瓜,大家围着轮流舀着吃,大家的目光都聚焦在西瓜上,也许只有在这一刻,我们才不会那样的打闹。我们都想吃最中间的部分,最红的,最甜的部分,可是又如同大人世界般,我们显得那样腼腆。最后,总是你一小口我一小口,把那中间红红的果肉吞进肚子里,更埋下友谊的种子。 日子深一脚浅一脚的过,学习似乎成了我们唯一的公同语言,我们也从一个被别人称为“造反派”的顽童变为一个学子。甚至有时,在哪儿碰见也只会向对方点点头,丝毫没有了小时烈日下奔跑的情谊。家里的那张破破的桌子也不知去向,取而代之的是一张豪华的青瓷桌…… 小学毕业后那年暑假的最后一天,刚刚步入六年级的他们来送别我,我们围坐在桌边,夏日的炎热似乎把我们所有要诉说的话都给憋了回去,我们都沉默着。冰爽的西瓜成了我们释放的对象,我们不再像小时那样子吃西瓜,所有的西瓜都被切成了片,有红,有青。红红的那部分就在最上面,我们之间的友情就像这样火红。 没有告别仪式,只是如青般离开。 “悄悄,是别离的笙箫” 迈入初中,一切都是陌生,交流变少了,浑浑噩噩的梦中,我又梦见了他们。 关了台灯,寂静与黑暗容我沉思。 初一就要结束的几天里,夏天悄无声息得把炎热带来,家人们又带回来了西瓜,复习之余,我又捧起了半个西瓜,这一回就我一人沉默。握着勺子,一口一口舀着慢慢品味。“嗯?”与瓜皮连着的青色果肉吸引了我。“啊!原来他们比中间的果肉更惹人迷!” 我舀了一勺,“咔嚓”,是多么清脆。 “但我不能放歌”,时光荏苒,十几年前的往事似乎又模模糊糊。 他们如流水划过,留下一道青色的痕迹。青,是青。 \ No newline at end of file diff --git a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java b/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java index 604b9172..d5a23f4c 100644 --- a/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java +++ b/sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java @@ -3,15 +3,23 @@ package com.gitee.sop.sdk; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.gitee.sop.sdk.client.OpenClient; +import com.gitee.sop.sdk.common.UploadFile; +import com.gitee.sop.sdk.model.DemoFileUploadModel; import com.gitee.sop.sdk.model.GetStoryModel; import com.gitee.sop.sdk.request.CommonRequest; +import com.gitee.sop.sdk.request.DemoFileUploadRequest; import com.gitee.sop.sdk.request.GetStoryRequest; import com.gitee.sop.sdk.response.CommonResponse; +import com.gitee.sop.sdk.response.DemoFileUploadResponse; import com.gitee.sop.sdk.response.GetStoryResponse; import junit.framework.TestCase; import org.junit.Test; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class SdkTest extends TestCase { @@ -70,4 +78,35 @@ public class SdkTest extends TestCase { } } + // 文件上传 + @Test + public void testUpload() throws IOException { + DemoFileUploadRequest request = new DemoFileUploadRequest(); + + DemoFileUploadModel model = new DemoFileUploadModel(); + model.setRemark("上传文件参数"); + request.setBizModel(model); + + List files = new ArrayList<>(); + String root = System.getProperty("user.dir"); + System.out.println(root); + files.add(new UploadFile("file1", new File(root + "/src/main/resources/file1.txt"))); + files.add(new UploadFile("file2", new File(root + "/src/main/resources/file2.txt"))); + request.setFiles(files); + + DemoFileUploadResponse response = client.execute(request); + + System.out.println("--------------------"); + if (response.isSuccess()) { + List responseFiles = response.getFiles(); + System.out.println("您上传的文件信息:"); + responseFiles.stream().forEach(file->{ + System.out.println(file); + }); + } else { + System.out.println("errorCode:" + response.getCode() + ",errorMsg:" + response.getMsg()); + } + System.out.println("--------------------"); + } + }