Day06

目录

问题1:传输给前端的时间格式不对

问题2:文件上传与下载

1、文件上传

2、文件下载

1、请求内联形式下载的后端响应方法

2、附件形式


问题1:传输给前端的时间格式不对

因为我们传递给前端的是Json对象,所以可以通过Jackson的ObjectMapper设置相应的序列化器与反序列化器,实现正确的格式转换

private ObjectMapper objectMapper() {
        final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
        ObjectMapper mapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
        javaTimeModule.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
        javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.registerModule(javaTimeModule);
        return mapper;
    }

 addSerializer()方法的第一个参数是要序列化的对象类型,第二个参数是序列化器

addDeserializer()方法的第一个参数是要反序列化的对象类型(即json要转为Java对象的类型),第二个参数是反序列化器

public <T> SimpleModule addSerializer(Class<? extends T> type, JsonSerializer<T> ser);
public <T> SimpleModule addDeserializer(Class<T> type, JsonDeserializer<? extends T> deser);

或者在要序列化的时间属性上添加@JsonFormat注解

@Data
public class Category implements Serializable {
  
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone  = "GMT+8", shape = JsonFormat.Shape.STRING)
    private LocalDateTime createTime;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8", shape = JsonFormat.Shape.STRING)
    private LocalDateTime updateTime;


}

@JsonFormat属性

shape 表示序列化后的一种类型,枚举类 pattern 表示日期的格式 timezone 默认是GMT,中国需要GMT+8 locale 根据位置序列化的一种格式,默认为本地的语言简称

问题2:文件上传与下载

1、文件上传

文件上传时,对页面的form表单有如下要求:

表单属性取值说明
methodpost必须选择post方式提交
enctypemultipart/form-data采用multipart格式上传文件
typefile使用input的file控件上传
<form method="post" action="/common/upload" enctype="multipart/form-data">
    <input name="myFile" type="file"  />
    <input type="submit" value="提交" /> 
</form>

后端可以使用MultipartFile来接收文件

//public Result<String> uploadImg(@RequestParam("file") MultipartFile multipartFile) {
@PostMapping("/upload")
    public Result<String> uploadImg(MultipartFile file) {
        String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String fileName = UUID.randomUUID().toString() + type;
        File parent = new File(basePath);
        if (!parent.exists()) {
            parent.mkdir();
        }
        File img = new File(basePath + fileName);
        try {
            file.transferTo(img);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.success(fileName);
    }

补充:

1、MultipartFile这个对象实际上是一个临时文件,由服务器存储到某个临时文件夹下,因此上传文件实际上就是把临时文件转存到项目的某个文件夹下。

2、MultipartFile的getName与getOriginalFileName方法的差别

getOriginalFileName:上传文件名,不同浏览器可能提交给服务端的文件名不同

getName:返回参数的名称,如(MultipartFile oriFile)则返回为oriFile

相关文章:MultipartFile详解

2、文件下载

文件下载分为两种;

  • 客户端以附件形式下载
  • 客户端以内联形式下载(在浏览器直接打开)

文件下载的本质是向浏览器传输字节,并且告诉浏览器该如何处理文件 。比如使用Content-Disposition,可以实现附件下载,或者设置content-type告诉浏览器文件类型,让它决定如何处理文件。

文件下载不一定要以流的形式返回给浏览器,可以先把文件全部读取到内存中,再把文件放在响应体中。

下面我们采用以流的形式返回,即从磁盘中读数据到内存的同时,将数据从内存中返回给前端

Content-Disposition的作用:告知浏览器以何种方式处理响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存

1、请求内联形式下载的后端响应方法
@RestController
@RequestMapping("/common")
public class CommonController {

    //不支持静态
    @Value("${reggie.basePath}")
    private String basePath;

    @GetMapping("/download")
    public void download(HttpServletResponse response, String name) {
        File file = new File(basePath + name);
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
            ServletOutputStream outputStream = response.getOutputStream();
            byte[] bytes = new byte[1024 * 1024];
            int len = 0;
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            log.info("找不到文件: " + file.getAbsolutePath());
        }

    }
}

在上述方法中,没有设置Content-Disposition,浏览器接收到二进制流后,默认是内联形式,直接打开。

2、附件形式
@GetMapping(value = "/test01")
    public void test01(HttpServletResponse response) throws IOException {
        File file = new File("D:\\springbootDemo\\src\\main\\resources\\picture\\729d14e6-9f91-4cbb-8f31-b423be35450f.jpg");
        byte[] bytes = new byte[1024 * 1024];
        int len = 0;
        FileInputStream fileInputStream = new FileInputStream(file);
        response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
        ServletOutputStream outputStream = response.getOutputStream();
        while ((len = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }

        outputStream.close();
        fileInputStream.close();
    }

补充:content-type:application/octet-stream

        告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载。
Application/octet-stream是应用程序文件的默认值。意思是未知的应用程序文件,浏览器一般不会自动执行或询问执行。浏览器会像对待,设置了HTTP头Content-Disposition值为attachment的文件一样来对待这类文件,即浏览器会触发下载行为。

        说人话就是,浏览器并不认得这是什么类型,也不知道应该如何展示,只知道这是一种二进制文件,因此遇到content-type为application/octet-stream的文件时,浏览器会直接把它下载下来。这个类型一般会配合另一个响应头Content-Disposition,该响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者网页的一部分),还是以附件的形式下载并保存到本地。
————————————————
版权声明:本文为CSDN博主「心潮的滴滴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42582773/article/details/121807555

 对于application/octet-stream,浏览器只会将其下载到本地,已经过测试。

@GetMapping(value = "/test01")
    public void test01(HttpServletResponse response) throws IOException {
        File file = new File("D:\\springbootDemo\\src\\main\\resources\\picture\\729d14e6-9f91-4cbb-8f31-b423be35450f.jpg");
        byte[] bytes = new byte[1024 * 1024];
        int len = 0;
        FileInputStream fileInputStream = new FileInputStream(file);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "inline; filename=" + file.getName());
        ServletOutputStream outputStream = response.getOutputStream();
        while ((len = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, len);
        }

        outputStream.close();
        fileInputStream.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值