• dropwizard中上传和下载文件


    传输格式基础知识

    MIME 类型

    MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。

    MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。

    MINE类型详细列表:https://www.w3school.com.cn/media/media_mimeref.asp

    multipart/form-data

    我们在通过 HTTP 向服务器发送 POST 请求提交数据,都是通过 form 表单形式提交的,如下:

    1. <FORM method="POST" action="http://w.sohu.com/t2/upload.do" enctype="multipart/form-data">
    2. <INPUT type="text" name="city" value="Santa colo">
    3. <INPUT type="text" name="desc">
    4. <INPUT type="file" name="pic">
    5. FORM>

    提交时会向服务器端发出这样的数据

    1. POST /t2/upload.do HTTP/1.1
    2. User-Agent: SOHUWapRebot
    3. Accept-Language: zh-cn,zh;q=0.5
    4. Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7
    5. Connection: keep-alive
    6. Content-Length: 60408
    7. Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
    8. Host: w.sohu.com
    9. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
    10. Content-Disposition: form-data; name="city"
    11. Santa colo
    12. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
    13. Content-Disposition: form-data;name="desc"
    14. Content-Type: text/plain; charset=UTF-8
    15. Content-Transfer-Encoding: 8bit
    16. ...
    17. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
    18. Content-Disposition: form-data;name="pic"; filename="photo.jpg"
    19. Content-Type: application/octet-stream
    20. Content-Transfer-Encoding: binary
    21. ... binary data of the jpg ...
    22. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--
    • application/x-www-urlencoded
    • multipart/form-data
    • text-plain

    默认情况下是 application/x-www-urlencoded,当表单使用 POST 请求时,数据会被以 x-www-urlencoded 方式编码到 Body 中来传送, 而如果 GET 请求,则是附在 url 链接后面来发送。GET 请求只支持 ASCII 字符集,因此,如果我们要发送更大字符集的内容,我们应使用 POST 请求。

    如果要发送大量的二进制数据(non-ASCII),"application/x-www-form-urlencoded" 显然是低效的。因此,这种情况下,应该使用 "multipart/form-data" 格式。

    参考:https://www.jianshu.com/p/29e38bcc8a1d

    代码实现

    依赖

    1. <dependency>
    2. <groupId>org.glassfish.jersey.mediagroupId>
    3. <artifactId>jersey-media-multipartartifactId>
    4. <version>2.33version>
    5. dependency>
    6. <dependency>
    7. <groupId>commons-iogroupId>
    8. <artifactId>commons-ioartifactId>
    9. <version>2.11.0version>
    10. dependency>

    接口实现

    1. package com.jsq.hibernate.resource;
    2. import com.google.common.collect.ImmutableMap;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.apache.commons.io.FileUtils;
    5. import org.apache.commons.io.IOUtils;
    6. import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
    7. import org.glassfish.jersey.media.multipart.FormDataParam;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.ws.rs.*;
    10. import javax.ws.rs.core.Context;
    11. import javax.ws.rs.core.MediaType;
    12. import javax.ws.rs.core.Response;
    13. import javax.ws.rs.core.StreamingOutput;
    14. import java.io.*;
    15. import java.util.Map;
    16. @Path("file")
    17. @Slf4j
    18. @Produces(MediaType.APPLICATION_JSON)
    19. public class FileResource {
    20. @POST
    21. @Path("upload")
    22. @Consumes(MediaType.MULTIPART_FORM_DATA)
    23. public Response uploadFile(@Context HttpServletRequest request,
    24. @FormDataParam("file") InputStream inputStream,
    25. @FormDataParam("file") FormDataContentDisposition formDataContentDisposition) {
    26. log.info("start tp upload");
    27. Map parameters = formDataContentDisposition.getParameters();
    28. log.info("parameters is {}", parameters);
    29. String fileName = formDataContentDisposition.getFileName();
    30. String path = "D:";
    31. File file = new File(path + File.separator + fileName);
    32. try (FileOutputStream outputStream = FileUtils.openOutputStream(file);
    33. BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
    34. IOUtils.copy(inputStream, bufferedOutputStream, 8192);
    35. return Response.ok().entity(ImmutableMap.of("code", 0, "message", "success")).build();
    36. } catch (IOException e) {
    37. return Response.ok().type(MediaType.APPLICATION_JSON).entity(ImmutableMap.of("code", 0, "message", e.getMessage())).build();
    38. }
    39. }
    40. @GET
    41. @Path("download")
    42. public Response downloadFile(@QueryParam("filename") String filename, @Context HttpServletRequest request) {
    43. Map parameterMap = request.getParameterMap();
    44. log.info("parameters of request is {}", parameterMap);
    45. String path = "D:";
    46. File file = new File(path + File.separator + filename);
    47. if (!file.exists()) {
    48. return Response.ok().entity(ImmutableMap.of("code", 1, "message", "file does not exist")).build();
    49. }
    50. return Response.ok().entity(file).header("Content-disposition", "attachment;filename=" + filename)
    51. .header("Cache-Control", "no-cache").build();
    52. }
    53. @GET
    54. @Path("download/stream")
    55. public Response downloadStream(@QueryParam("filename") String filename, @Context HttpServletRequest request) throws IOException {
    56. Map parameterMap = request.getParameterMap();
    57. log.info("parameters of request is {}", parameterMap);
    58. String path = "D:";
    59. File file = new File(path + File.separator + filename);
    60. if (!file.exists()) {
    61. return Response.ok().entity(ImmutableMap.of("code", 1, "message", "file does not exist")).build();
    62. }
    63. return Response.ok().entity(new StreamingOutput() {
    64. @Override
    65. public void write(OutputStream output) throws IOException, WebApplicationException {
    66. output.write(FileUtils.readFileToByteArray(file));
    67. }
    68. }).header("Content-disposition", "attachment;filename=" + filename)
    69. .header("Cache-Control", "no-cache").build();
    70. }
    71. }

    上传文件

    1. @Consumes(MediaType.MULTIPART_FORM_DATA),消费的是表单样式

    2. @Produces(MediaType.APPLICATION_JSON),返回的响应是json样式

    3. 输入参数:@FormDataParam("file") InputStream inputStream,文件流

    4. 输入参数:@FormDataParam("file") FormDataContentDisposition formDataContentDisposition,文件相关信息

    5. 将输入的流转化为文件存于本地

    6. postman操作

    下载文件

    1. 两种下载文件的方式:文件形式和流的形式
    2. 响应头中放入"Content-disposition", "attachment;filename=" + filename,**Content-Disposition**响应标头是指示内容是否预期在浏览器中内联显示的标题,即,作为网页或作为网页的一部分或作为附件下载并且本地保存
    3. header中相关知识点见:https://cloud.tencent.com/developer/section/1189916

    启动类

    1. package com.jsq.hibernate;
    2. import com.jsq.hibernate.config.HelloWorldConfiguration;
    3. import com.jsq.hibernate.resource.FileResource;
    4. import io.dropwizard.Application;
    5. import io.dropwizard.setup.Bootstrap;
    6. import io.dropwizard.setup.Environment;
    7. import org.glassfish.jersey.media.multipart.MultiPartFeature;
    8. import java.net.URL;
    9. public class HelloWorldApplication extends Application {
    10. public static void main(String[] args) throws Exception {
    11. URL yml = HelloWorldApplication.class.getClassLoader().getResource("server.yml");
    12. String configFile = yml.getFile();
    13. System.out.println(configFile);
    14. args = new String[]{"server", configFile};
    15. new HelloWorldApplication().run(args);
    16. }
    17. @Override
    18. public void run(HelloWorldConfiguration helloWorldConfiguration, Environment environment) {
    19. environment.jersey().register(new MultiPartFeature());
    20. environment.jersey().register(new FileResource());
    21. }
    22. @Override
    23. public String getName() {
    24. return "hello-world";
    25. }
    26. @Override
    27. public void initialize(Bootstrap bootstrap) {
    28. }
    29. }

    注:

    1. MultiPartFeature必须注册
    2. 注册Resource类
  • 相关阅读:
    【编程题】【Scratch四级】2022.09 绘制图形
    mysql8修改密码
    博弈论——反应函数
    SpringBoot基础篇 (4)—SSMP整合案例
    详解机器学习中的数据处理(二)——特征归一化
    【.NET】控制台应用程序的各种交互玩法
    《Vue入门到精通之vue-router路由详解》
    Ab-darknet在darknet-ros环境下编译报错如何解决
    学生个人网页模板 简单个人主页--贝聿铭人物介绍 6页带表单 带报告3800字
    流水线作业模拟程序
  • 原文地址:https://blog.csdn.net/jsq916/article/details/126542720