gateway支持文件上传

1.x
tanghc 5 years ago
parent 9067a34118
commit 0bc0432ac3
  1. 78
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java
  2. 116
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java
  3. 46
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java
  4. 387
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java
  5. 20
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java
  6. 5
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java

@ -1,78 +0,0 @@
package com.gitee.sop.gatewaycommon.gateway;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP;
import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY;
/**
* @author tanghc
*/
public class GatewayContext extends ApiContext {
/**
* 获取请求参数
* @param exchange
* @return
*/
public static ApiParam getApiParam(ServerWebExchange exchange) {
return exchange.getAttribute(SopConstants.CACHE_API_PARAM);
}
/**
* 设置请求参数
* @param exchange
* @param apiParam
*/
public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) {
exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam);
}
/**
* 获取Spring Cloud Gateway请求的原始参数前提是要使用ReadBodyRoutePredicateFactory
* @param exchange
* @return 没有参数返回null
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
*/
public static Map<String, String> getRequestParams(ServerWebExchange exchange) {
Map<String, String> params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP);
if (params != null) {
return params;
}
if (exchange.getRequest().getMethod() == HttpMethod.GET) {
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
params = buildParams(queryParams);
} else {
String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
if (cachedBody != null) {
params = RequestUtil.parseQueryToMap(cachedBody);
}
}
if (params != null) {
exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params);
}
return params;
}
private static Map<String, String> buildParams(MultiValueMap<String, String> queryParams) {
if (queryParams == null || queryParams.size() == 0) {
return null;
}
Map<String, String> params = new HashMap<>(queryParams.size());
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
String val = entry.getValue().get(0);
params.put(entry.getKey(), val);
}
return params;
}
}

@ -0,0 +1,116 @@
package com.gitee.sop.gatewaycommon.gateway;
import com.alibaba.fastjson.JSON;
import com.gitee.sop.gatewaycommon.bean.SopConstants;
import com.gitee.sop.gatewaycommon.gateway.common.ServletFileUploadUtil;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP;
import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY;
/**
* @author tanghc
*/
public class ServerWebExchangeUtil {
/**
* 获取请求参数
* @param exchange ServerWebExchange
* @return 返回请求参数
*/
public static ApiParam getApiParam(ServerWebExchange exchange) {
return exchange.getAttribute(SopConstants.CACHE_API_PARAM);
}
/**
* 设置请求参数
* @param exchange ServerWebExchange
* @param apiParam 请求参数
*/
public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) {
exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam);
}
/**
* 获取Spring Cloud Gateway请求的原始参数前提是要使用ReadBodyRoutePredicateFactory
* @param exchange ServerWebExchange
* @return 没有参数返回null
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
*/
public static Map<String, ?> getRequestParams(ServerWebExchange exchange) {
Map<String, ?> params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP);
if (params != null) {
return params;
}
if (exchange.getRequest().getMethod() == HttpMethod.GET) {
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
params = buildParams(queryParams);
} else {
String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
if (cachedBody != null) {
MediaType contentType = exchange.getRequest().getHeaders().getContentType();
String contentTypeStr = contentType == null ? "" : contentType.toString().toLowerCase();
// 如果是json方式提交
if (StringUtils.containsAny(contentTypeStr, "json", "text")) {
params = JSON.parseObject(cachedBody);
} else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) {
// 如果是文件上传请求
HttpServletRequest fileUploadRequest = ServletFileUploadUtil.getFileUploadRequest(exchange, cachedBody);
params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest);
} else {
params = RequestUtil.parseQueryToMap(cachedBody);
}
}
}
if (params != null) {
exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params);
}
return params;
}
public static Map<String, String> buildParams(MultiValueMap<String, String> queryParams) {
if (queryParams == null || queryParams.size() == 0) {
return null;
}
Map<String, String> params = new HashMap<>(queryParams.size());
for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
params.put(entry.getKey(), entry.getValue().get(0));
}
return params;
}
/**
* 添加header
* @param exchange 当前ServerWebExchange
* @param headersConsumer headers
* @return 返回一个新的ServerWebExchange
*/
public static ServerWebExchange addHeaders(ServerWebExchange exchange, Consumer<HttpHeaders> headersConsumer) {
// 创建一个新的request
ServerHttpRequest serverHttpRequestNew = exchange.getRequest()
.mutate()
.headers(headersConsumer)
.build();
// 将现在的request 变成 change对象
return exchange
.mutate()
.request(serverHttpRequestNew)
.build();
}
}

@ -0,0 +1,46 @@
package com.gitee.sop.gatewaycommon.gateway.common;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.IOException;
public class ByteArrayStreamWrapper extends ServletInputStream {
private byte[] data;
private int idx = 0;
/**
* Creates a new <code>ServletInputStreamWrapper</code> instance.
*
* @param data a <code>byte[]</code> value
*/
public ByteArrayStreamWrapper(byte[] data) {
if (data == null)
data = new byte[0];
this.data = data;
}
@Override
public int read() throws IOException {
if (idx == data.length)
return -1;
// I have to AND the byte with 0xff in order to ensure that it is returned as an unsigned integer
// the lack of this was causing a weird bug when manually unzipping gzipped request bodies
return data[idx++] & 0xff;
}
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}

@ -0,0 +1,387 @@
package com.gitee.sop.gatewaycommon.gateway.common;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
/**
* 上传文件的request
*
* @author tanghc
*/
public class FileUploadHttpServletRequest implements HttpServletRequest {
private ServerHttpRequest serverHttpRequest;
private byte[] data;
public FileUploadHttpServletRequest(ServerHttpRequest serverHttpRequest, byte[] data) {
this.serverHttpRequest = serverHttpRequest;
this.data = data;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ByteArrayStreamWrapper(data);
}
@Override
public int getContentLength() {
return data.length;
}
@Override
public long getContentLengthLong() {
return data.length;
}
@Override
public String getAuthType() {
return null;
}
@Override
public Cookie[] getCookies() {
return new Cookie[0];
}
@Override
public long getDateHeader(String s) {
return 0;
}
@Override
public String getHeader(String s) {
return null;
}
@Override
public Enumeration<String> getHeaders(String s) {
return null;
}
@Override
public Enumeration<String> getHeaderNames() {
return null;
}
@Override
public int getIntHeader(String s) {
return 0;
}
@Override
public String getMethod() {
return HttpMethod.POST.name();
}
@Override
public String getPathInfo() {
return null;
}
@Override
public String getPathTranslated() {
return null;
}
@Override
public String getContextPath() {
return "/";
}
@Override
public String getQueryString() {
return null;
}
@Override
public String getRemoteUser() {
return null;
}
@Override
public boolean isUserInRole(String s) {
return false;
}
@Override
public Principal getUserPrincipal() {
return null;
}
@Override
public String getRequestedSessionId() {
return null;
}
@Override
public String getRequestURI() {
return null;
}
@Override
public StringBuffer getRequestURL() {
return null;
}
@Override
public String getServletPath() {
return null;
}
@Override
public HttpSession getSession(boolean b) {
return null;
}
@Override
public HttpSession getSession() {
return null;
}
@Override
public String changeSessionId() {
return null;
}
@Override
public boolean isRequestedSessionIdValid() {
return false;
}
@Override
public boolean isRequestedSessionIdFromCookie() {
return false;
}
@Override
public boolean isRequestedSessionIdFromURL() {
return false;
}
@Override
public boolean isRequestedSessionIdFromUrl() {
return false;
}
@Override
public boolean authenticate(HttpServletResponse httpServletResponse) throws IOException, ServletException {
return false;
}
@Override
public void login(String s, String s1) throws ServletException {
}
@Override
public void logout() throws ServletException {
}
@Override
public Collection<Part> getParts() throws IOException, ServletException {
return null;
}
@Override
public Part getPart(String s) throws IOException, ServletException {
return null;
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> aClass) throws IOException, ServletException {
return null;
}
@Override
public Object getAttribute(String s) {
return null;
}
@Override
public Enumeration<String> getAttributeNames() {
return null;
}
@Override
public String getCharacterEncoding() {
return null;
}
@Override
public void setCharacterEncoding(String s) throws UnsupportedEncodingException {
}
@Override
public String getContentType() {
return serverHttpRequest.getHeaders().getContentType().toString();
}
@Override
public String getParameter(String s) {
return null;
}
@Override
public Enumeration<String> getParameterNames() {
return null;
}
@Override
public String[] getParameterValues(String s) {
return new String[0];
}
@Override
public Map<String, String[]> getParameterMap() {
return null;
}
@Override
public String getProtocol() {
return null;
}
@Override
public String getScheme() {
return null;
}
@Override
public String getServerName() {
return null;
}
@Override
public int getServerPort() {
return 0;
}
@Override
public BufferedReader getReader() throws IOException {
return null;
}
@Override
public String getRemoteAddr() {
return null;
}
@Override
public String getRemoteHost() {
return null;
}
@Override
public void setAttribute(String s, Object o) {
}
@Override
public void removeAttribute(String s) {
}
@Override
public Locale getLocale() {
return null;
}
@Override
public Enumeration<Locale> getLocales() {
return null;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public RequestDispatcher getRequestDispatcher(String s) {
return null;
}
@Override
public String getRealPath(String s) {
return null;
}
@Override
public int getRemotePort() {
return 0;
}
@Override
public String getLocalName() {
return null;
}
@Override
public String getLocalAddr() {
return null;
}
@Override
public int getLocalPort() {
return 0;
}
@Override
public ServletContext getServletContext() {
return null;
}
@Override
public AsyncContext startAsync() throws IllegalStateException {
return null;
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
return null;
}
@Override
public boolean isAsyncStarted() {
return false;
}
@Override
public boolean isAsyncSupported() {
return false;
}
@Override
public AsyncContext getAsyncContext() {
return null;
}
@Override
public DispatcherType getDispatcherType() {
return null;
}
}

@ -0,0 +1,20 @@
package com.gitee.sop.gatewaycommon.gateway.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.server.ServerWebExchange;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
/**
* @author tanghc
*/
@Slf4j
public class ServletFileUploadUtil {
public static HttpServletRequest getFileUploadRequest(ServerWebExchange exchange, String requestBody) {
byte[] data = requestBody.getBytes(StandardCharsets.UTF_8);
return new FileUploadHttpServletRequest(exchange.getRequest(), data);
}
}

@ -101,9 +101,8 @@ public class RequestUtil {
* @return 返回表单中的字段内容
*/
public static Map<String, String> convertMultipartRequestToMap(HttpServletRequest request) {
DiskFileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
// 创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
Map<String, String> params = new HashMap<>(16);
try {
List<FileItem> fileItems = upload.parseRequest(request);

Loading…
Cancel
Save