¡Acostúmbrate a escribir juntos! Este es el día 15 de mi participación en el "Desafío de actualización de abril del nuevo plan diario de Nuggets", haga clic para ver los detalles del evento .
FingirSubirDescargar
fondo del problema
Basado en algunos de los marcos principales actuales, que son básicamente 微服务
arquitecturas utilizadas, las funciones de administración de archivos a menudo se file
extraen a un 微服务
ejemplo independiente file微服务
.
¡ Las solicitudes de front-end, todas llaman a la función de suma file微服务
de archivos de una manera unificada ! ! !上传
下载
¡Parece que no hay nada malo con tal diseño, administración unificada! ! !
Debido a que el archivo se carga, es posible que también deba escribirse 业务数据
, por ejemplo, 附件的信息
etc., que debe extraerse en un microservicio independiente para 前端
su uso.
Entonces habrá un problema: ! ! ! T_T
1. ¿Qué sucede si mis archivos adjuntos no se cargan a través de la interfaz? Soy un servicio back-end y necesito guardar un archivo adjunto, entonces, ¿qué estás haciendo?
2. Un servicio en mi backend necesita leer un archivo y analizarlo. Debido a que es una arquitectura distribuida, se puede
file微服务
implementar服务器A
allí . ¿Cómo debemos后端服务
implementarlo服务B
, de modo que磁盘路径
el archivo no se pueda leer en absoluto? con ella ¿Paño de lana?
Hmmmm, lo que dijiste tiene sentido, ¡es realmente un gran problema! ! !
¡No se asuste, resolveremos este problema hoy! ! !
Porque la invocación de la interfaz entre nuestros servicios, en el 微服务
sistema, generalmente se realiza mediante feign
desintonización. Entonces, ¿también se puede feign
llamar al archivo?
La respuesta es definitivamente sí, ¡jaja! ! ! ^_^
No hay muchas tonterías, ¡vamos al código! ! !
Preparación de la interfaz fingir
- Definir una
Feign
interfaz de carga y descarga
@FeignClient(name = "file", configuration = {FileClient.MultipartSupportConfig.class})
public interface FileClient {
/**
* 上传文件
* @param file
* @return
*/
@RequestMapping(path = "/file/upload", consumes = {"multipart/form-data"})
JsonResult upload(@RequestPart(name="file") MultipartFile file);
/**
* 下载文件
*/
@GetMapping(path = "/file/download/{fileId}")
Response download(@PathVariable(name = "fileId") String fileId);
public class MultipartSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder feignFormEncoder() {
return new SpringFormEncoder();
}
}
}
复制代码
file微服务
Proporcionar上传
interfaz de archivo
@RequestMapping("/file/upload")
public JsonResult upload(MultipartHttpServletRequest request) throws Exception {
JsonResult jsonResult = new JsonResult();
String timestamp = request.getParameter("time");
MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
List<MultipartFile> files = multiFileMap.get("files");
if (BeanUtil.isEmpty(files)) {
files = multiFileMap.get("file");
}
Iterator<MultipartFile> it = files.iterator();
while (it.hasNext()) {
MultipartFile multipartFile = it.next();
//保存到磁盘
multipartFile.transferTo(new File("文件路径"));
//记录文件上传业务数据
...
xxxxFileDao.saveFile(xxxFile);
}
jsonResult.setSuccess(true);
jsonResult.setData(fileList);
jsonResult.setMessage("成功上传!");
return jsonResult;
}
复制代码
file微服务
Proporcionar下载
interfaz de archivo
@GetMapping("/download/{fileId}")
public void feigndownloadOne(@PathVariable("fileId") String fileId, HttpServletResponse response) throws Exception {
//通过fileId查找文件
...
xxxFile = xxxxFileDao.getFile(fileId);
File file = new File("文件路径");
String filename = xxxFile.getName();
String type ="attachment";
response.setHeader("Content-Disposition", type + ";filename=" + filename);
FileInputStream fis = new FileInputStream(file);
BufferedInputStream buff = null;
OutputStream out = null;
try {
buff = new BufferedInputStream(fis);
out = response.getOutputStream();
IOUtils.copy(buff, out);
} finally {
out.flush();//注意out流,对象不能close
fis.close();
buff.close();
}
}
复制代码
下载
这个接口,有个比较重要的地方就是,out
流,不能close()
,否则就算获取到该流,也无法处理业务逻辑。
好了
,上面就是咋们定义好的feign接口,和提供服务的file微服务
上传下载接口!!!
上传下载接口,只是给出一个demo,大家伙,可自行修改,相应的业务逻辑!!!^_^
Feign上传下载
接下来,咋们就开始使用到这个feign
的上传下载
功能!!!
- 上传
feign接口
,使用
import java.io.File;
import java.io.FileInputStream;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;
import org.apache.http.entity.ContentType;
File pdfFile = new File("D://test.pdf");
FileInputStream fileInputStream = new FileInputStream(pdfFile);
MultipartFile multipartFile = new MockMultipartFile(pdfFile.getName(), pdfFile.getName(),
ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
//上传
JsonResult jsonResult = fileClient.upload(multipartFile);
if (jsonResult.isSuccess() && jsonResult.getCode() == 200) {
}
复制代码
注意了
注意了
注意了
!!!
这里,有个要注意的地方,因为我们的
upload
接口,即controller
接口一般使用MultipartFile
对象接收文件,那么我们就得把File
,对象先转成MultipartFile
对象,才可以调通这个接口!!!转换方式,看上面代码即可!!!
好了,这个就是上传文件的示例
,也是比较简单
啦!!!
- 下载
feign接口
,使用
import feign.Response;
//文件流
Response response = fileClient.download(fileId);
InputStream in = null;
if(response.status() == 200){
Response.Body body = response.body();
in = body.asInputStream();
//拿到这个in流,处理相应的业务逻辑
...
//处理完成后,记得关闭一下inputStream流
if(in != null){
in.close();
}
}
复制代码
注意了
注意了
注意了
!!!
这里有两个地方需要注意:
1.因为我们的download接口,
out
流是还没有close()
,所以这里的in
流,用完得close()
一下。2.这里的代码,在开发过程中,不能
打断点调试
,不能打断点调试
,不能打断点调试
!!!重要的事情得说三遍,不能
打断点调试
,因为你断点调试后
,这里的in
流,会因为执行了toString()
方法,导致in
流被关闭
了,无法再使用,即不能处理业务逻辑代码了!!!
好了,这个就是上传文件的示例
,也是比较简单
啦!!!
好了,Feign
上传和下载,大概的实现,就是这样了!!!^_^
¡Entonces podemos escribir código felizmente! ! ! ^_^