eml.studio.server.file.FileDownloadServlet.java Source code

Java tutorial

Introduction

Here is the source code for eml.studio.server.file.FileDownloadServlet.java

Source

/**
 * Copyright 2017 Institute of Computing Technology, Chinese Academy of Sciences.
 * Licensed under the terms of the Apache 2.0 license.
 * Please see LICENSE file in the project root for terms
 */
package eml.studio.server.file;

import eml.studio.server.constant.Constants;
import eml.studio.server.util.HDFSIO;

import org.apache.hadoop.fs.Path;

import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;

public class FileDownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final String DOWNLOAD_BASE_DIR = "./download";
    private static final Integer FILE_BUFFER_SIZE = 4096;

    private static Logger logger = Logger.getLogger(FileDownloadServlet.class.getName());

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        saveDownloadFile(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        saveDownloadFile(request, response);
    }

    /**
     * Save download file
     *
     * @param req HttpServletRequest
     * @param resp HttpServletResponse
     * @throws ServletException
     * @throws IOException
     */
    protected void saveDownloadFile(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String filename = req.getParameter("filename");
        logger.info("Download file:" + filename);

        if (filename == null) {
            resp.sendError(0, "Missing file Name");
            logger.warning("[Missing file Name]");
            return;
        }
        resp.setContentType("application/octet-stream");
        if (!HDFSIO.isDirectory(new Path(filename))) //??
        {
            logger.info("Directory download file:" + filename);
            resp.addHeader("Content-Disposition", "attachment; filename=\"" + filename);
            InputStream in = HDFSIO.downInputStream(Constants.NAME_NODE + "/" + filename);
            ServletOutputStream out = resp.getOutputStream();
            byte[] buffer = new byte[FILE_BUFFER_SIZE];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
            in.close();
            out.flush();
            out.close();
        } else //If the directory, then download the directory from HDFS to the server,
               // and then compressed, and then download to the client
        {
            resp.addHeader("Content-Disposition", "attachment; filename=\"" + filename + ".zip");
            String[] filePathStrs = filename.split("/");
            String dirName = filePathStrs[filePathStrs.length - 1]; //??(?)

            String localDirPath = DOWNLOAD_BASE_DIR + "/" + dirName; //?

            long startTime = System.currentTimeMillis();

            //Download the results directory from HDFS to local (if it not exist)
            if (!new File(DOWNLOAD_BASE_DIR + "/" + dirName).exists()) {
                downloadFile(filename);
                logger.info("Download dir success, save path is : " + localDirPath);
            } else
                logger.info(localDirPath + " has exist!");

            //Compress the resulting file in zip format (if it does not exist)
            String zipFilePath = localDirPath + ".zip";
            if (!new File(zipFilePath).exists()) {
                zipFiles(localDirPath, zipFilePath);
                logger.info("Compress dir success, save paths is : " + zipFilePath);
            } else
                logger.info(zipFilePath + " has exist!");

            FileInputStream in = new FileInputStream(zipFilePath);
            ServletOutputStream out = resp.getOutputStream();
            byte[] buffer = new byte[FILE_BUFFER_SIZE];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
            in.close();
            out.flush();
            out.close();
            long endTime = System.currentTimeMillis();
            logger.info("Download time:" + (endTime - startTime));

            File results = new File(DOWNLOAD_BASE_DIR);
            if (results.exists()) {
                deleteFile(results.getAbsolutePath());
                logger.info("Delete result dir success!");
            }
        }

    }

    /**
     * Download files or files from HDFS to local
     *
     * @param filePath  File or file directory path (HDFS path)
     * @throws IOException
     */
    public static void downloadFile(String filePath) throws IOException {
        String[] paths = filePath.split("/");
        String fileName = paths[paths.length - 1];
        String baseDir = "";
        download(filePath, fileName, baseDir);
    }

    /**
     * Method of download file from HDFS
     * 
     * @param filePath File or directory path (HDFS path)
     * @param fileName  file name
     * @param baseDir  path of parent file
     * @throws IOException
     */
    private static void download(String filePath, String fileName, String baseDir) throws IOException {
        Path uri = new Path(filePath);
        if (HDFSIO.isDirectory(uri)) {
            File dirFile = new File(DOWNLOAD_BASE_DIR + "/" + baseDir + fileName);
            if (!dirFile.exists()) {
                logger.info("Download mkdir:" + dirFile.getPath());
                dirFile.mkdirs();
            }
            Path[] paths = HDFSIO.list(filePath);
            for (Path p : paths)
                download(p.toString(), p.getName(), baseDir + fileName + "/");
        } else {
            InputStream in = HDFSIO.downInputStream(filePath);
            logger.info("Download file:" + DOWNLOAD_BASE_DIR + "/" + baseDir + fileName);
            File file = new File(DOWNLOAD_BASE_DIR + "/" + baseDir + fileName);
            if (!file.exists())
                file.createNewFile();
            FileOutputStream out = new FileOutputStream(file);
            byte[] buffer = new byte[FILE_BUFFER_SIZE];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
            in.close();
            out.flush();
            out.close();
        }
    }

    /**
     * Compressed file or directory
     * 
     * @param srcPath  The address of the file or folder
     * @param zipFilePath  The address of the compressed package
     */
    public static void zipFiles(String srcPath, String zipFilePath) {
        File file = new File(srcPath);
        if (!file.exists())
            throw new RuntimeException(srcPath + "not exist?");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(zipFilePath);
            CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream, new CRC32());
            ZipOutputStream out = new ZipOutputStream(cos);
            String baseDir = "";
            zip(file, out, baseDir);
            out.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Main method of compress the file
     * 
     * @param file  origin file
     * @param out  compressed file stream
     * @param baseDir  file path
     */
    private static void zip(File file, ZipOutputStream out, String baseDir) {
        if (file.isDirectory()) {
            logger.info("Compress dir:" + baseDir + file.getName());
            zipDirectory(file, out, baseDir);
        } else {
            logger.info("Compress file:" + baseDir + file.getName());
            zipSingleFile(file, out, baseDir);
        }
    }

    /**
     * If a compressed directory is recursively compressed
     *  
     * @param dir  diretory
     * @param out  compressed file stream
     * @param baseDir  The relative position of the files in the catalog
     */
    private static void zipDirectory(File dir, ZipOutputStream out, String baseDir) {
        if (!dir.exists())
            return;

        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            zip(files[i], out, baseDir + dir.getName() + "/");
        }
    }

    /**
     * Compress a single file
     *  
     * @param file file
     * @param out  file stream
     * @param baseDir  The relative address of the file
     */
    private static void zipSingleFile(File file, ZipOutputStream out, String baseDir) {
        if (!file.exists()) {
            return;
        }
        try {
            int buffer = FILE_BUFFER_SIZE;
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            out.putNextEntry(entry);
            int count;
            byte data[] = new byte[buffer];
            while ((count = bis.read(data, 0, buffer)) != -1) {
                out.write(data, 0, count);
            }
            bis.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Delete a file or directory
     * 
     * @param path  path of file or directory
     * @return type:boolean
     */
    private static boolean deleteFile(String path) {
        File delFile = new File(path);
        if (delFile.isDirectory()) {
            File[] dirFiles = delFile.listFiles();
            for (File f : dirFiles) {
                deleteFile(f.getAbsolutePath());
            }
        }
        return delFile.delete();
    }

}