SpringBoot搭建的Web服务文本文件和gzip下载

简介

本文主要介绍基于SpringBoot搭建的Web服务,对于文本文件(txt)和文本文件压缩包(gzip)的下载操作。

下载操作

由于我们主要介绍文本文件的下载操作,将重点集中在Controller中方法的实现,对于SpringBoot搭建Web服务就不再介绍。

基于SpringBoot搭建Web服务可参考另外一篇博文:基于SpringBoot搭建Web服务

下载操作包含3个类型

  • 将字符串写入到文件中提供下载
  • 下载本地文本文件
  • 本地文本文件转成GZIP压缩包下载

Controller

新建DownloadController.class 添加@RestController注解,代码如下:

package hello.controller;

import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

/**
 * Created on 2018/12/20.
 *
 * @author Marvin Yang
 */
@RestController
public class DownloadController {
    
}

将字符串写入到文件中下载

DownloadController.class 中添加方法downloadFile实现将字符串写入到文件中并提供下载操作。有两点需要注意,(1) 函数无返回值;(2) 选择HttpServletResponse作为返回。

	/**
     * txt文件下载接口
     *  1. 将字符串写入到文件中提供下载
     *
     * @param response a HttpServletResponse
     */
    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public void downloadFile(HttpServletResponse response) {
        // set header
        response.setHeader("Content-Disposition", "attachment; filename=demo.txt");
        String demo = "Here is a demo of download file.";
        try {
            response.getOutputStream().write(demo.getBytes());
            response.flushBuffer();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

在浏览器请求,测试样例如下:

# 8080是web端口 
http://localhost:8080/download?

下载本地文本文件

DownloadController.class 中添加方法downloadLocalFile实现本地文本文件的下载操作。有3点需要注意,(1) URL调用方式为/download/{fileName} ; (2) InputStream必须close(),否则一旦接口被调用,该文件在本地则不允许删除,除非关闭web服务; (3) 注意本地文件的路径,保证可以获取到。

	/**
     * 下载本地文本文件
     *  1. FileInputStream必须close, 否则会被占用, 导致如果web服务不关闭文件无法被本地删除
     *
     * @param fileName 本地文本文件名称
     * @param response a HttpServletResponse
     */
    @RequestMapping(value = "/download/{fileName}", method = RequestMethod.GET)
    public void downloadLocalFile(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        // set header
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        FileInputStream inputStream = null;
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                String errorMsg = "Can not find such file: " + fileName;
                response.getOutputStream().write(errorMsg.getBytes());
            } else {
                inputStream = new FileInputStream(fileName);
                IOUtils.copy(inputStream, response.getOutputStream());
            }
            response.flushBuffer();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignore) {}
            }
        }
    }

在浏览器请求,测试样例如下:

# 8080是web端口
# demo_local是本地文件名称(注意文件路径)
http://localhost:8080/download/demo_local?

本地文本文件转成GZIP压缩包下载

DownloadController.class 中添加方法downloadLocalFile实现本地文本文件读取并转换为gzip下载。有2点需要注意,(1) 设置content-type; (2) response.getOutputStream()需要使用GZIPOutputStream

	 /**
     * 本地文本文件转成GZIP压缩包下载
     *  1. FileInputStream必须close, 否则会被占用, 导致如果web服务不关闭文件无法被本地删除
     *
     * @param fileName 本地文本文件名称
     * @param response HttpServletResponse
     */
    @RequestMapping(value = "/download/zip/{fileName}", method = RequestMethod.GET)
    public void downloadLocalGZip(@PathVariable("fileName") String fileName, HttpServletResponse response) {
        // set header
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".gz");
        response.setContentType("application/zip");
        FileInputStream inputStream = null;
        try (GZIPOutputStream outputStream = new GZIPOutputStream(response.getOutputStream())){
            File file = new File(fileName);
            if (!file.exists()) {
                String errorMsg = "can not find such file: " + fileName;
                response.getOutputStream().write(errorMsg.getBytes());
            } else {
                inputStream = new FileInputStream(fileName);
                IOUtils.copy(inputStream, outputStream);
            }
            response.flushBuffer();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignore) {}
            }
        }
    }

在浏览器请求,测试样例如下:

# 8080是web端口
# demo_local是本地文件名称(注意文件路径)
http://localhost:8080/download/zip/demo_local?

总结

我们介绍了RestControllerservice服务提供文本文件和gzip压缩包的下载操作。

如果是读取其他类型的文件,则尝试修改InputStream的类型完成文件读取;如果是zip类型的文件下载,则可以使用java.util.zip.ZipOutputStream,注意zip的操作不同于gzip操作。

参考文献

https://stackoverflow.com/questions/27952949/spring-rest-create-zip-file-and-send-it-to-the-client/40498539#40498539

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中实现高效的GZIP压缩可以通过配置来实现。下面是一个示例: 1. 在`application.properties`或`application.yml`文件中添加以下配置: ```yaml server.compression.enabled=true server.compression.mime-types=application/json,application/xml,text/html,text/css,text/javascript,application/javascript ``` 2. 在启动类中添加`@EnableCompression`注解: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletContextInitializer; import org.springframework.context.annotation.Bean; import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import javax.servlet.DispatcherType; import javax.servlet.ServletContext; import javax.servlet.ServletException; import java.util.EnumSet; @SpringBootApplication @EnableWebMvc public class BootDemoApplication implements WebMvcConfigurer, ServletContextInitializer { public static void main(String[] args) { SpringApplication.run(BootDemoApplication.class, args); } @Override public void onStartup(ServletContext servletContext) throws ServletException { EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD); FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter = new FilterRegistrationBean<>(); characterEncodingFilter.setFilter(new CharacterEncodingFilter()); characterEncodingFilter.addInitParameter("encoding", "UTF-8"); characterEncodingFilter.addInitParameter("forceEncoding", "true"); characterEncodingFilter.setDispatcherTypes(dispatcherTypes); characterEncodingFilter.addUrlPatterns("/*"); FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter = new FilterRegistrationBean<>(); shallowEtagHeaderFilter.setFilter(new ShallowEtagHeaderFilter()); shallowEtagHeaderFilter.setDispatcherTypes(dispatcherTypes); shallowEtagHeaderFilter.addUrlPatterns("/*"); servletContext.addFilter("characterEncodingFilter", characterEncodingFilter.getFilter()).addMappingForUrlPatterns(dispatcherTypes, true, "/*"); servletContext.addFilter("shallowEtagHeaderFilter", shallowEtagHeaderFilter.getFilter()).addMappingForUrlPatterns(dispatcherTypes, true, "/*"); } @Bean public FilterRegistrationBean<GzipFilter> gzipFilter() { FilterRegistrationBean<GzipFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new GzipFilter()); registrationBean.addUrlPatterns("/*"); return registrationBean; } } ``` 请注意,上述示例中的`GzipFilter`是自定义的GZIP过滤器,你需要根据自己的需求实现该过滤器。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值