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());
}
}
文章图片
生成的文件及其内容.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
文章图片
swagger-ui.png
文章图片
swagger接口示例.png
文章图片
swagger接口示例.png 点击try it out真正分发出请求:
文章图片
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;
}
文章图片
通过使用注解描述方法和参数.png 2.使用WireMock快速伪造RESTful服务 WireMock实际上是一个独立的服务器,通过他的客户端写一些代码来编辑该服务器,告诉服务器收到什么请求返回什么响应;可以随时通过客户端代码和api改变服务器的行为,服务器一直运行,不需要重启,不需要反复部署。
文章图片
使用wiremock服务器.png ①下载wiremock:http://wiremock.org/docs/running-standalone/
文章图片
下载wiremock.png ②启动wiremock:使用命令$ java -jar wiremock-standalone-2.17.0.jar
注:在Windows上是不需要$这个的,直接是java -jar wiremock-standalone-2.17.0.jar
文章图片
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单独拿出去:
文章图片
把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"}
推荐阅读
- 热闹中的孤独
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- Activiti(一)SpringBoot2集成Activiti6
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募