SpringBoot中文件上传与下载&swagger的使用

SpringBoot中文件上传与下载&swagger的使用 一、文件上传 单元测试:

//模拟上传文件 @Test public void whenUploadSuccess() throws Exception { String result = mockMvc.perform(fileUpload("/file") .file(new MockMultipartFile("file","test.txt","multipart/form-data","hello upload".getBytes("UTF-8")))) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); System.out.println(result); //{"path":"D:\\WorkSpaces\\stsWS\\hcx-security-demo\\src\\main\\java\\com\\hcx\\web\\controller\\1524895173355.txt"} }

Controller:
@RestController @RequestMapping("/file") public class FileController {@PostMapping public FileInfo upload(MultipartFile file) throws Exception{System.out.println(file.getName()); //file System.out.println(file.getOriginalFilename()); //test.txt System.out.println(file.getSize()); //12 String folder = "D:\\WorkSpaces\\stsWS\\hcx-security-demo\\src\\main\\java\\com\\hcx\\web\\controller"; File localFile = new File(folder,new Date().getTime()+".txt"); file.transferTo(localFile); return new FileInfo(localFile.getAbsolutePath()); } }

SpringBoot中文件上传与下载&swagger的使用
文章图片
生成的文件及其内容.png 二、文件下载
package com.hcx.web.controller; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.hcx.web.dto.FileInfo; @RestController @RequestMapping("/file") public class FileController {private String folder = "D:\\\\WorkSpaces\\\\stsWS\\\\hcx-security-demo\\\\src\\\\main\\\\java\\\\com\\\\hcx\\\\web\\\\controller"; @PostMapping public FileInfo upload(MultipartFile file) throws Exception{System.out.println(file.getName()); //file System.out.println(file.getOriginalFilename()); //test.txt System.out.println(file.getSize()); //12 String folder = "D:\\WorkSpaces\\stsWS\\hcx-security-demo\\src\\main\\java\\com\\hcx\\web\\controller"; File localFile = new File(folder,new Date().getTime()+".txt"); file.transferTo(localFile); return new FileInfo(localFile.getAbsolutePath()); }@GetMapping("/{id}") public void download(@PathVariable String id,HttpServletRequest request,HttpServletResponse response) throws Exception{ try( InputStream inputStream = new FileInputStream(new File(folder,id+".txt")); OutputStream outputStream = response.getOutputStream(); ){ response.setContentType("application/x-download"); response.addHeader("Content-Disposition", "attachment; filename=test.txt"); IOUtils.copy(inputStream, outputStream); outputStream.flush(); } }}

启动项目,在浏览器中访问:localhost:8060/file/1524895173355
三、与前端并行工作 1.使用swagger自动生成html文档
通过该文档可以把写的RESTfulAPI向前端描述清楚
根据代码自动生成文档;
改过代码之后,也可以自动更新文档,而不用手动再去修改文档
第一步:添加依赖:
Springfox Swagger2:扫描文件,生成文档数据
io.springfox springfox-swagger2 2.7.0

Springfox Swagger UI:生成最终看到的可视化界面
io.springfox springfox-swagger-ui 2.7.0

第二步:在DemoApplication启动类中添加注解:@EnableSwagger2
@SpringBootApplication @RestController @EnableSwagger2 public class DemoApplication {public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }@GetMapping("/hello") public String hello() { return "hello spring security"; }}

启动项目,访问localhost:8060/swagger-ui.html
页面列出了系统所有的Controller和endpoint
SpringBoot中文件上传与下载&swagger的使用
文章图片
swagger-ui.png SpringBoot中文件上传与下载&swagger的使用
文章图片
swagger接口示例.png SpringBoot中文件上传与下载&swagger的使用
文章图片
swagger接口示例.png 点击try it out真正分发出请求:
SpringBoot中文件上传与下载&swagger的使用
文章图片
tryitout.png 但是对于每个字段,文档中并没能给出具体的含义,可以通过注解来达到此要求:
①描述方法:@ApiOperation(value="https://www.it610.com/article/用户查询服务")
该value会默认替换成方法名
②参数描述:
第一种情况:当参数为一个对象时:在对象相应的属性上添加注解@ApiModelProperty(value=""):
public class UserQueryCondition { private String username; @ApiModelProperty(value="https://www.it610.com/article/用户年龄起始值") private int age; @ApiModelProperty(value="https://www.it610.com/article/用户年龄终止值") private int ageTo; private String weight; }

第二种情况:参数直接是基本数据类型,没有封装对象,使用@ApiParam(""):
@GetMapping("/{id:\\d+}") @JsonView(User.UserDetailView.class) public User getInfo(@ApiParam("用户id") @PathVariable String id) { //throw new UserNotExistException(id); System.out.println("进入getInfo服务"); User user = new User(); user.setUsername("tom"); return user; }

SpringBoot中文件上传与下载&swagger的使用
文章图片
通过使用注解描述方法和参数.png 2.使用WireMock快速伪造RESTful服务 WireMock实际上是一个独立的服务器,通过他的客户端写一些代码来编辑该服务器,告诉服务器收到什么请求返回什么响应;可以随时通过客户端代码和api改变服务器的行为,服务器一直运行,不需要重启,不需要反复部署。
SpringBoot中文件上传与下载&swagger的使用
文章图片
使用wiremock服务器.png ①下载wiremock:http://wiremock.org/docs/running-standalone/
SpringBoot中文件上传与下载&swagger的使用
文章图片
下载wiremock.png ②启动wiremock:使用命令$ java -jar wiremock-standalone-2.17.0.jar
注:在Windows上是不需要$这个的,直接是java -jar wiremock-standalone-2.17.0.jar
SpringBoot中文件上传与下载&swagger的使用
文章图片
wiremock启动界面.png ③添加wiremock依赖:
com.github.tomakehurst wiremock 2.5.1

【SpringBoot中文件上传与下载&swagger的使用】编写代码:
package com.hcx.web.wiremock; import com.github.tomakehurst.wiremock.client.WireMock; //该类是一个客户端,要连接后台启动的服务器 public class MockServer {public static void main(String[] args) { //告诉服务器,如何处理外界的请求 //指明服务器的位置 WireMock.configureFor(8062); //此处在本地,所以不需要再指定ip了 WireMock.removeAllMappings(); //把之前的配置都清空//伪造一个测试桩 WireMock.stubFor(WireMock.get(WireMock.urlEqualTo("/order/1")) .willReturn(WireMock.aResponse().withBody("{\"id\":1}") .withStatus(200))); } }

此时访问浏览器localhost:8062/order/1可以得到对应的结果:
{"id":1}

对代码进行重构:
把json单独拿出去:
SpringBoot中文件上传与下载&swagger的使用
文章图片
把json单独写进一个文件里.png 修改代码:
package com.hcx.web.wiremock; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.springframework.core.io.ClassPathResource; import com.github.tomakehurst.wiremock.client.WireMock; //该类是一个客户端,要连接后台启动的服务器 public class MockServer {public static void main(String[] args) throws Exception{ //告诉服务器,如何处理外界的请求 //指明服务器的位置 WireMock.configureFor(8062); //此处在本地,所以不需要再指定ip了 WireMock.removeAllMappings(); //把之前的配置都清空mock("/order/1","01"); //加其服务 mock("/order/2","02"); }public static void mock(String url,String file) throws IOException { ClassPathResource resource = new ClassPathResource("mock/response/"+file+".txt"); String content = StringUtils.join(FileUtils.readLines(resource.getFile(),"UTF-8").toArray(),"\n"); //FileUtils.readFileToString(resource.getFile()); //伪造一个测试桩 WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(url)) .willReturn(WireMock.aResponse().withBody(content) .withStatus(200))); } }

01.txt:
{ "id":1, "type":"A"}

    推荐阅读