[business scenario] - connect with the download interface of the third party, download the files provided by the third party to the server, and support batch and single download of files on the server on the client. Generally, there is a special file server for this scenario. This project involves the company's contract and is used by a few people in the company, so it is stored on the project server (you need to specify the download location).
There is not much nonsense. The code is divided into three parts
-
Download the file to the server;
public void downloadToService(String documentId) { if (StringUtil.isBlank(documentId)) { throw new BusinessException("Only contracts with download status completed are supported"); } ContractExample example = new ContractExample(); example.createCriteria().andDocumentIdEqualTo(documentId); Contract contract = contractMapper.selectOneByExample(example); if (contract == null) { throw new BusinessException("Download the contract according to the contract file Id No corresponding contract found"); } FileOutputStream outputDoc = null; try { // Specify that when downloading files to a folder, you need to build the folder in advance String linuxPath = System.getProperty("user.home"); log.info("Download files to Linux The path for is:{}", linuxPath + "/folder/" + contract.getContractName() + ".pdf"); outputDoc = new FileOutputStream(linuxPath + "/folder/" + contract.getContractName() + ".pdf"); } catch (FileNotFoundException e) { e.printStackTrace(); } signService.downloadDoc(Long.parseLong(documentId), outputDoc); safeClose(outputDoc); log.info("The contract was downloaded to the server successfully)"); }
-
Single download is in the form of file stream;
public ResponseEntity<byte[]> download(String contractName, int type) throws IOException { String fileName; if (type == 1) { // Single download pdf file fileName = contractName + ".pdf"; } else { // Download zip file in bulk fileName = contractName + ".zip"; } //Get file location String linuxPath = System.getProperty("user.home"); log.info("Where users download files:{}", linuxPath + "/folder/" + fileName); //Add the file to the input stream InputStream in = new FileInputStream(new File(linuxPath + "/folder/" + fileName)); // Returns the estimated number of bytes remaining that the next method called on this input stream can read (or skip) from this input stream without blocking byte[] body = new byte[in.available()]; //Read into the input stream in.read(body); //Prevent Chinese miscoding fileName = new String(fileName.getBytes("gbk"), "iso8859-1"); //Set response header HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=" + fileName); return new ResponseEntity<byte[]>(body, headers, HttpStatus.OK); }
-
The bulk download is divided into three parts: making the files (multiple) to be downloaded into compressed packages (zip/rar) - "downloading the compressed packages" and "deleting the compressed packages";
When providing the interface in the background, you can use GET to directly return the responseentity < byte [] >. Here you can try the page request, and the download interface will pop up directly to select the download location, and the foreground will directly thank the url for calling.public ResponseEntity<byte[]> batchDownload(List<String> contractNames) throws IOException { //Get file location String linuxPath = System.getProperty("user.home"); List<File> fileList = new ArrayList<>(); // Add a directory of files to download to the list of files to compress contractNames.forEach(cn -> fileList.add(new File(linuxPath + "/folder/" + cn + ".pdf"))); File file = new File(linuxPath + "/folder/XXXX contract.zip"); FileOutputStream fos = new FileOutputStream(file); // Compression tools (to be provided below) ZipUtils.toZip(fileList, fos); // Call download transfer to foreground ResponseEntity<byte[]> response = download("XXXX contract", 2); // Delete the downloaded zip package (save space) boolean delete = file.delete(); log.info("Whether the downloaded server file is deleted successfully:{}", delete); return response; }
-
ZipUtils compression tool class
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipUtils { private static final int BUFFER_SIZE = 2 * 1024; /** * Compress to ZIP method 1 * * @param srcDir Compress folder path * @param out Compressed file output stream * @param KeepDirStructure Whether to keep the original directory structure, true: keep the directory structure; * false:All files run to the root directory of the compressed package (Note: files with the same name may appear if the directory structure is not preserved, and compression fails) */ public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure) throws RuntimeException { long start = System.currentTimeMillis(); ZipOutputStream zos = null; try { zos = new ZipOutputStream(out); File sourceFile = new File(srcDir); compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure); long end = System.currentTimeMillis(); System.out.println("Compression complete, time consuming:" + (end - start) + " ms"); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils", e); } finally { if (zos != null) { try { zos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Compress to ZIP method 2 * * @param srcFiles List of files to be compressed * @param out Compressed file output stream */ public static void toZip(List<File> srcFiles, OutputStream out) throws RuntimeException { long start = System.currentTimeMillis(); ZipOutputStream zos = null; try { zos = new ZipOutputStream(out); for (File srcFile : srcFiles) { byte[] buf = new byte[BUFFER_SIZE]; zos.putNextEntry(new ZipEntry(srcFile.getName())); int len; FileInputStream in = new FileInputStream(srcFile); while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } zos.closeEntry(); in.close(); } long end = System.currentTimeMillis(); System.out.println("Compression complete, time consuming:" + (end - start) + " ms"); } catch (Exception e) { throw new RuntimeException("zip error from ZipUtils", e); } finally { if (zos != null) { try { zos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Recursive compression method * * @param sourceFile source file * @param zos zip Output stream * @param name Compressed name * @param KeepDirStructure Whether to keep the original directory structure, true: keep the directory structure; * false:All files run to the root directory of the compressed package (Note: files with the same name may appear if the directory structure is not preserved, and compression fails) */ private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure) throws Exception { byte[] buf = new byte[BUFFER_SIZE]; if (sourceFile.isFile()) { // Add a zip entity to the zip output stream, and the name of the file whose name is the zip entity in the constructor zos.putNextEntry(new ZipEntry(name)); // copy file to zip output stream int len; FileInputStream in = new FileInputStream(sourceFile); while ((len = in.read(buf)) != -1) { zos.write(buf, 0, len); } // Complete the entry zos.closeEntry(); in.close(); } else { File[] listFiles = sourceFile.listFiles(); if (listFiles == null || listFiles.length == 0) { // When you need to keep the original file structure, you need to process the empty folder if (KeepDirStructure) { // Handling of empty folders zos.putNextEntry(new ZipEntry(name + "/")); // No file, no file copy required zos.closeEntry(); } } else { for (File file : listFiles) { // Determine whether to keep the original file structure if (KeepDirStructure) { // Note: file.getName() needs to be preceded by the name of the parent folder plus a slash, // Otherwise, the original file structure cannot be preserved in the final compression package, that is, all the files run to the root directory of the compression package compress(file, zos, name + "/" + file.getName(), KeepDirStructure); } else { compress(file, zos, file.getName(), KeepDirStructure); } } } } } }