diff --git a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java index ddaed44f..378b699a 100644 --- a/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java +++ b/sop-common/sop-registry-api/src/main/java/com/gitee/sop/registryapi/bean/HttpTool.java @@ -13,6 +13,7 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.ResponseBody; import org.apache.commons.codec.digest.DigestUtils; import java.io.ByteArrayOutputStream; @@ -51,14 +52,17 @@ public class HttpTool { protected void initHttpClient(HttpToolConfig httpToolConfig) { httpClient = new OkHttpClient.Builder() - .connectTimeout(httpToolConfig.connectTimeoutSeconds, TimeUnit.SECONDS) // 设置链接超时时间,默认10秒 + // 设置链接超时时间,默认10秒 + .connectTimeout(httpToolConfig.connectTimeoutSeconds, TimeUnit.SECONDS) .readTimeout(httpToolConfig.readTimeoutSeconds, TimeUnit.SECONDS) .writeTimeout(httpToolConfig.writeTimeoutSeconds, TimeUnit.SECONDS) .cookieJar(new CookieJar() { + @Override public void saveFromResponse(HttpUrl httpUrl, List list) { cookieStore.put(httpUrl.host(), list); } + @Override public List loadForRequest(HttpUrl httpUrl) { List cookies = cookieStore.get(httpUrl.host()); return cookies != null ? cookies : new ArrayList(); @@ -204,22 +208,24 @@ public class HttpTool { * @return * @throws IOException */ - public String requestFile(String url, Map form, Map header, List files) + public String requestFile(String url, Map form, Map header, List files) throws IOException { // 创建MultipartBody.Builder,用于添加请求的数据 MultipartBody.Builder bodyBuilder = new MultipartBody.Builder(); bodyBuilder.setType(MultipartBody.FORM); for (UploadFile uploadFile : files) { - bodyBuilder.addFormDataPart(uploadFile.getName(), // 请求的名字 - uploadFile.getFileName(), // 文件的文字,服务器端用来解析的 - RequestBody.create(null, uploadFile.getFileData()) // 创建RequestBody,把上传的文件放入 + // 请求的名字 + bodyBuilder.addFormDataPart(uploadFile.getName(), + // 文件的文字,服务器端用来解析的 + uploadFile.getFileName(), + // 创建RequestBody,把上传的文件放入 + RequestBody.create(null, uploadFile.getFileData()) ); } - Set> entrySet = form.entrySet(); - for (Map.Entry entry : entrySet) { - bodyBuilder.addFormDataPart(entry.getKey(), entry.getValue()); + for (Map.Entry entry : form.entrySet()) { + bodyBuilder.addFormDataPart(entry.getKey(), String.valueOf(entry.getValue())); } RequestBody requestBody = bodyBuilder.build(); @@ -238,6 +244,51 @@ public class HttpTool { } } + /** + * 请求数据 + * + * @param url 请求url + * @param form 请求数据 + * @param header header + * @return 返回Response + * @throws IOException + */ + public Response requestForResponse(String url, Map form, Map header, HTTPMethod method) throws IOException { + Request.Builder requestBuilder = buildRequestBuilder(url, form, method); + // 添加header + addHeader(requestBuilder, header); + + Request request = requestBuilder.build(); + return httpClient + .newCall(request) + .execute(); + } + + /** + * 下载文件 + * + * @param url 请求url + * @param form 请求数据 + * @param header header + * @return 返回文件流 + * @throws IOException + */ + public InputStream downloadFile(String url, Map form, Map header) throws IOException { + Request.Builder requestBuilder = buildRequestBuilder(url, form, HTTPMethod.GET); + // 添加header + addHeader(requestBuilder, header); + + Request request = requestBuilder.build(); + Response response = httpClient + .newCall(request) + .execute(); + if (response.isSuccessful()) { + ResponseBody body = response.body(); + return body == null ? null : body.byteStream(); + } + return null; + } + private void addHeader(Request.Builder builder, Map header) { if (header != null) { Set> entrySet = header.entrySet(); @@ -256,10 +307,15 @@ public class HttpTool { } public enum HTTPMethod { + /** http GET */ GET, + /** http POST */ POST, + /** http PUT */ PUT, + /** http HEAD */ HEAD, + /** http DELETE */ DELETE; private HTTPMethod() { diff --git a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/DownloadController.java b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/DownloadController.java index 88e2091b..044f0c2d 100644 --- a/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/DownloadController.java +++ b/sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/DownloadController.java @@ -2,15 +2,15 @@ package com.gitee.sop.storyweb.controller; import com.gitee.sop.servercommon.annotation.ApiMapping; import com.gitee.sop.storyweb.controller.param.StoryParam; -import org.apache.commons.io.FileUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; -import java.io.File; import java.io.IOException; /** @@ -18,20 +18,24 @@ import java.io.IOException; * * @author tanghc */ +@Api(tags = "文件下载") @Controller public class DownloadController { - @ApiMapping(value = "story.download") - public ResponseEntity export(StoryParam param) throws IOException { + @ApiOperation(value = "文件下载", notes = "演示文件下载") + @ApiMapping(value = "story.download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE/* 这个一定要加,不然沙箱文档不起作用 */) + public ResponseEntity download(StoryParam param) throws IOException { HttpHeaders headers = new HttpHeaders(); // 假设下载classpath下的application.properties文件 ClassPathResource resource = new ClassPathResource("/application.properties"); - File file = resource.getFile(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); - headers.setContentDispositionFormData("attachment", file.getName()); + headers.setContentDispositionFormData("attachment", resource.getFilename()); - return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); + return ResponseEntity + .ok() + .headers(headers) + .body(IOUtils.toByteArray(resource.getInputStream())); } } diff --git a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java index 671347dc..55145558 100644 --- a/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java +++ b/sop-test/src/main/java/com/gitee/sop/test/HttpTool.java @@ -244,6 +244,26 @@ public class HttpTool { } } + /** + * 请求数据 + * + * @param url 请求url + * @param form 请求数据 + * @param header header + * @return 返回Response + * @throws IOException + */ + public Response requestForResponse(String url, Map form, Map header, HTTPMethod method) throws IOException { + Request.Builder requestBuilder = buildRequestBuilder(url, form, method); + // 添加header + addHeader(requestBuilder, header); + + Request request = requestBuilder.build(); + return httpClient + .newCall(request) + .execute(); + } + /** * 下载文件 * diff --git a/sop-website/website-front/pages/sandbox/sandbox.js b/sop-website/website-front/pages/sandbox/sandbox.js index 27b63f90..0aba4c29 100644 --- a/sop-website/website-front/pages/sandbox/sandbox.js +++ b/sop-website/website-front/pages/sandbox/sandbox.js @@ -138,6 +138,12 @@ function doTest() { } }); data.bizContent = JSON.stringify(bizContent); + if (isDownloadRequest(currentItem)) { + data.isDownloadRequest = true; + downloadFile(data); + // window.open() + return; + } // 确定文件数量,并且知道参数名称 if (uploadFileObjects.length > 0) { var formData = new FormData(); @@ -151,6 +157,20 @@ function doTest() { } } +function isDownloadRequest(currentItem) { + var produces = currentItem.produces; + if (!produces) { + return false; + } + for (var i = 0; i < produces.length; i++) { + var produce = produces[i]; + if (produce.indexOf('application/octet-stream') > -1) { + return true; + } + } + return false; +} + function putVal(obj, input) { if (input.type == 'text') { obj[input.name] = input.value; @@ -204,6 +224,16 @@ function postFile(data, formData) { }); } +function downloadFile(data) { + $('.dl-form').remove(); + var url = SopConfig.url + '/sandbox/test'; + var form = $('
').attr("action", url).attr("method", "get"); + for(var key in data) { + form.append($("").attr("type", "hidden").attr("name", key).attr("value", data[key])); + } + form.appendTo('body').submit(); +} + function successHandler(resp) { setReqInfo(resp); showRespnfo(resp.apiResult); diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java index 00762c52..cc62daaf 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java @@ -20,6 +20,10 @@ public class DocItem { /** http method列表 */ private Collection httpMethodList; + private Collection produces; + + + List requestParameters; List responseParameters; diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java index 25a20024..6363b85c 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java @@ -1,12 +1,16 @@ package com.gitee.sop.websiteserver.controller; import com.gitee.sop.registryapi.bean.HttpTool; -import com.gitee.sop.registryapi.bean.HttpTool.*; +import com.gitee.sop.registryapi.bean.HttpTool.HTTPMethod; +import com.gitee.sop.registryapi.bean.HttpTool.UploadFile; import com.gitee.sop.websiteserver.sign.AlipayApiException; import com.gitee.sop.websiteserver.sign.AlipaySignature; import com.gitee.sop.websiteserver.util.UploadUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import okhttp3.Headers; +import okhttp3.Response; +import okhttp3.ResponseBody; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.http.NameValuePair; @@ -26,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Collection; @@ -60,7 +65,10 @@ public class SandboxController { , @RequestParam String version , @RequestParam String bizContent , @RequestParam(defaultValue = "get") String httpMethod - , HttpServletRequest request) throws AlipayApiException { + , @RequestParam(defaultValue = "false") boolean isDownloadRequest + , HttpServletRequest request + , HttpServletResponse response + ) throws AlipayApiException { Assert.isTrue(StringUtils.isNotBlank(appId), "AppId不能为空"); Assert.isTrue(StringUtils.isNotBlank(privateKey), "PrivateKey不能为空"); @@ -111,7 +119,21 @@ public class SandboxController { try { String responseData; - if (!CollectionUtils.isEmpty(files)) { + if (isDownloadRequest) { + Response resp = httpTool.requestForResponse(url, params, Collections.emptyMap(), HTTPMethod.GET); + Headers respHeaders = resp.headers(); + ResponseBody body = resp.body(); + if (body == null) { + return null; + } + respHeaders + .names() + .forEach(name -> response.setHeader(name, respHeaders.get(name))); + + IOUtils.copy(body.byteStream(), response.getOutputStream()); + response.flushBuffer(); + return null; + } else if (!CollectionUtils.isEmpty(files)) { responseData = httpTool.requestFile(url, params, Collections.emptyMap(), files); } else { responseData = httpTool.request(url, params, Collections.emptyMap(), HTTPMethod.fromValue(httpMethod)); diff --git a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java index 6bf8a1cc..26a1d25c 100644 --- a/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java +++ b/sop-website/website-server/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java @@ -92,6 +92,7 @@ public class SwaggerDocParser implements DocParser { docItem.setSummary(docInfo.getString("summary")); docItem.setDescription(docInfo.getString("description")); docItem.setMultiple(docInfo.getString("multiple") != null); + docItem.setProduces(docInfo.getJSONArray("produces").toJavaList(String.class)); String moduleName = this.buildModuleName(docInfo, docRoot); docItem.setModule(moduleName); List docParameterList = this.buildRequestParameterList(docInfo, docRoot);