java implements the function of file download (attach the code that can be actually run)

Keywords: less Linux

Recently, I am working on a project, which involves file download and package compression download. Single file download is relatively simple. Multi file download involves package and compression knowledge, which I haven't done before. Write a blog to make a simple record. Less gossip, code:

The following codes are test codes, which can be used in practice:

/**
 * @author renxiang.fan
 * @version 1.0
 * @date 2019/7/9
 * @description File download controller
 **/
@RestController
@RequestMapping("/file")
public class FileController {

    private static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private DownLoadService downLoadService;

    /**
     * Single file download
     *
     * @param fileName Real file name
     */
    @GetMapping("/down-one")
    public void downOneFile(@RequestParam(value = "filename", required = false) String fileName) {
        logger.info("Input parameter of single file download interface:[filename={}]", fileName);
        if (fileName.isEmpty()) {
            return;
        }
        try {
            downLoadService.downOneFile(fileName);
        } catch (Exception e) {
            logger.error("Single file download interface exception:{fileName={},ex={}}", fileName, e);
        }
    }

    /**
     * Bulk package download file
     *
     * @param fileName File names, multiple separated by commas
     */
    @GetMapping("/down-together")
    public void downTogether(@RequestParam(value = "filename", required = false) String fileName) {
        logger.info("Batch packaging file download interface input:[filename={}]", fileName);
        if (fileName.isEmpty()) return;
        List<String> fileNameList = Arrays.asList(fileName.split(","));
        if (CollectionUtils.isEmpty(fileNameList)) return;
        try {
            downLoadService.downTogetherAndZip(fileNameList);
        } catch (Exception e) {
            logger.error("Exception in downloading interface of bulk package file:{fileName={},ex={}}", fileName, e);
        }
    }
}
/**
 * @author renxiang.fan
 * @version 1.0
 * @date 2019/7/9
 * @description File download service
 **/
@Service
public class DownLoadServiceImpl implements DownLoadService {

    private static final Logger logger = LoggerFactory.getLogger(DownLoadServiceImpl.class);

    @Value("${file.path}")
    private String FILE_ROOT_PATH;

    /**
     * Single file download
     *
     * @param fileName Single file name
     * @throws Exception
     */
    @Override
    public void downOneFile(String fileName) throws Exception {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        File file = new File(FILE_ROOT_PATH + fileName);
        if (file.exists()) {
            resp.setContentType("application/x-msdownload");
            resp.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO-8859-1"));
            InputStream inputStream = new FileInputStream(file);
            ServletOutputStream ouputStream = resp.getOutputStream();
            byte b[] = new byte[1024];
            int n;
            while ((n = inputStream.read(b)) != -1) {
                ouputStream.write(b, 0, n);
            }
            ouputStream.close();
            inputStream.close();
        }
    }

    /**
     * File bulk packaging and downloading
     *
     * @param fileNameList Multiple file names separated by commas
     * @throws IOException
     */
    @Override
    public void downTogetherAndZip(List<String> fileNameList) throws IOException {
        HttpServletResponse resp = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        resp.setContentType("application/x-msdownload");
        //Temporarily set the name of the compressed download file to test.zip
        resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
        String str = "";
        String rt = "\r\n";
        ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream());
        for (String filename : fileNameList) {
            str += filename + rt;
            File file = new File(FILE_ROOT_PATH + filename);
            zos.putNextEntry(new ZipEntry(filename));
            FileInputStream fis = new FileInputStream(file);
            byte b[] = new byte[1024];
            int n = 0;
            while ((n = fis.read(b)) != -1) {
                zos.write(b, 0, n);
            }
            zos.flush();
            fis.close();
        }
        //Set the comment content after decompressing the file
        zos.setComment("download success:" + rt + str);
        zos.flush();
        zos.close();
    }
}

Run, test, ok~

Digression

The OSS file server of Alibaba cloud is used in our project. The used partners will find that what is returned from the OSS server is an "OSSObject" object. Through the OSSObject object, only the corresponding InputStream can be obtained. At that time, we just started to do it. The idea is to write the InputStream directly to ZipOutputStream, which has not been possible. After half a day's tossing, I decided to temporarily write the InputStream to the linux server running the service, and then read the file. When I write the file to the ZipOutputStream class, I can delete the file directly and solve my problem successfully.

Posted by Drannon on Sun, 03 Nov 2019 02:41:08 -0800