diff --git a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/HttpTool.java b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/HttpTool.java index 2b86578c..63e43ef2 100644 --- a/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/bean/HttpTool.java +++ b/sop-admin/sop-admin-server/src/main/java/com/gitee/sop/adminserver/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; @@ -243,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(); 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/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java index 00762c52..cc62daaf 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/bean/DocItem.java +++ b/sop-website/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/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java index d1cac2e7..61623a8b 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/bean/HttpTool.java +++ b/sop-website/src/main/java/com/gitee/sop/websiteserver/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; @@ -243,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(); diff --git a/sop-website/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java index 9c122e86..7afb7bd2 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java +++ b/sop-website/src/main/java/com/gitee/sop/websiteserver/controller/SandboxController.java @@ -6,6 +6,9 @@ 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; @@ -25,6 +28,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; @@ -59,7 +63,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不能为空"); @@ -110,7 +117,21 @@ public class SandboxController { try { String responseData; - if (!CollectionUtils.isEmpty(files)) { + if (isDownloadRequest) { + Response resp = httpTool.requestForResponse(url, params, Collections.emptyMap(), HttpTool.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(), HttpTool.HTTPMethod.fromValue(httpMethod)); @@ -118,6 +139,7 @@ public class SandboxController { result.apiResult = responseData; return result; } catch (Exception e) { + log.error("请求失败", e); throw new RuntimeException("请求失败"); } } diff --git a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java b/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java index 6bf8a1cc..26a1d25c 100644 --- a/sop-website/src/main/java/com/gitee/sop/websiteserver/manager/SwaggerDocParser.java +++ b/sop-website/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); diff --git a/sop-website/src/main/resources/public/pages/sandbox/sandbox.js b/sop-website/src/main/resources/public/pages/sandbox/sandbox.js index 27b63f90..4be1e3cf 100644 --- a/sop-website/src/main/resources/public/pages/sandbox/sandbox.js +++ b/sop-website/src/main/resources/public/pages/sandbox/sandbox.js @@ -92,21 +92,21 @@ function createTreeTable(id, data) { cols: [[ {field: 'name', title: '参数',width: 200} ,{field: 'val', title: '值', width: 300, templet:function (row) { - var id = currentItem.nameVersion + '-' + row.name; - var requiredTxt = row.required ? 'required lay-verify="required"' : ''; - var module = row.module; - var type = row.type == 'file' ? 'file' : 'text'; - var attrs = [ - 'id="' + id + '"' - , 'name="'+row.name+'"' - , 'class="layui-input test-input"' - , 'type="' + type + '"' - , requiredTxt - , 'module="'+module+'"' - ]; + var id = currentItem.nameVersion + '-' + row.name; + var requiredTxt = row.required ? 'required lay-verify="required"' : ''; + var module = row.module; + var type = row.type == 'file' ? 'file' : 'text'; + var attrs = [ + 'id="' + id + '"' + , 'name="'+row.name+'"' + , 'class="layui-input test-input"' + , 'type="' + type + '"' + , requiredTxt + , 'module="'+module+'"' + ]; - return !row.refs ? '' : ''; - }} + return !row.refs ? '' : ''; + }} ,{field: 'description', title: '描述'} ]] }); @@ -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);