设想场景

为方便老师录入大量学生图片信息,在添加照片时,学生的相关资料以身份证号码+图片描述命名如
(1231231234567+一寸照片.jpg)
(1231231234567+身份证正面照片.jpg)
(1231231234567+身份证背面照片.jpg)
(1231231234567+毕业证照片.jpg)
(1231231233123+学位证照片.jpg)
压缩zip后上传保存学生资料
并实现后续可下载指定学生的资料包。

实现流程

就是一读写操作。

下面是代码实现

@PostMapping("/importZip")
public void importZip(MultipartFile file) {
    studentService.importZip(file);
}
import org.springframework.mock.web.MockMultipartFile;

	public void importZip(MultipartFile file) {
	    Map<String, MultipartFile> fileMap = new HashMap<>();
	    try {
	        // 获取zip文件输入流
	        ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream(), Charset.forName("GBK"));
	        // 转成 名字对应文件流的map
	        fileMap = convertToMultipartFile(zipInputStream);
	        
	        for (Map.Entry<String, MultipartFile> stringFileEntry : fileMap.entrySet()) {
		        // 上传并返回新文件名称
		        // 上传这块走自己的接口咯、目的是上传图片后获取url保存起来
		        String url = FileUploadUtils.upload(filePath, stringFileEntry.getValue());
	        }
	       
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	}
	

	public static  Map<String, MultipartFile> convertToMultipartFile(ZipInputStream zipInputStream) throws IOException {
		 Map<String, MultipartFile> result = new HashMap<>();
		   // 读取zip文件中的条目
		   ZipEntry zipEntry = zipInputStream.getNextEntry();
		   while (zipEntry != null) {
		       if (!zipEntry.isDirectory()) {
		           byte[] bytes = readAllBytesFromZipInputStream(zipInputStream);
		           // 创建MockMultipartFile并返回
		           result.put(zipEntry.getName(), new MockMultipartFile(zipEntry.getName(), zipEntry.getName(),"", new ByteArrayInputStream(bytes)));
		           zipInputStream.closeEntry();
		       }
		       zipEntry = zipInputStream.getNextEntry();
		   }
		   zipInputStream.close();
	
	    return result;
	}
	

	public static byte[] readAllBytesFromZipInputStream(ZipInputStream zipInputStream) throws IOException {
		  ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		    byte[] buffer = new byte[1024];
		    int bytesRead;
		    while ((bytesRead = zipInputStream.read(buffer)) != -1) {
		        byteArrayOutputStream.write(buffer, 0, bytesRead);
		    }
	    return byteArrayOutputStream.toByteArray();
	}

好的、上面的代码可以实现导入zip并且把压缩包里的文件名和文件流一一返回给你了。

你只需要把文件流调上传你的接口、并把文件名和url存下来,后面会用到。

下面我们来说说、正面把上传的文件、压缩成zip 导出。

	public void download(HttpServletResponse response, String studentId) {
	
		//!!!把你的资料获取出来!!!
		List<String> imageUrls = null;
		//!!!把你的资料获取出来!!!
		
		// 创建一个临时文件夹,用于存放下载的图片
        File tempFolder = new File("/newFile");
        tempFolder.mkdirs();
		try {
            // 遍历图片URL列表,下载并压缩图片
            for (String imageUrl : imageUrls) {
                try (BufferedInputStream in = new BufferedInputStream(bufferedReader(imageUrl));
                     FileOutputStream fileOutputStream = new FileOutputStream(tempFolder.getPath() + "/" +  imageUrl.substring(imageUrl.lastIndexOf("/") + 1))) {

                    byte[] dataBuffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
                        fileOutputStream.write(dataBuffer, 0, bytesRead);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            // 创建临时压缩文件
            File zipFile = File.createTempFile("相关资料", ".zip");
            FileOutputStream fos = new FileOutputStream(zipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);

            // 压缩文件夹内的文件
            File folder = new File(tempFolder.getPath());
            compressFolder(folder, zos);
            // 关闭流
            zos.close();
            fos.close();

            // 设置响应头
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFile.getName() + ".zip\"");

            // 将压缩文件写入响应输出流
            FileInputStream fis = new FileInputStream(zipFile);
            BufferedInputStream bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            bis.close();
            fis.close();
            os.flush();
            os.close();

            // 删除临时压缩文件
            zipFile.delete();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
             //删除临时文件夹及其文件
            deleteFolder(tempFolder);
        }
	}

	public InputStream bufferedReader(String url) throws IOException {
		//!!!!设置超时时间、不然遇到偶发性的url失效找不到图片就会直接报错、后面都不走了!!!
        URL downloadUrl = new URL(urlEncodeChinese(url));
        HttpURLConnection httpURLConnection = (HttpURLConnection) downloadUrl.openConnection();
        httpURLConnection.setRequestMethod("GET");
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        httpURLConnection.setUseCaches(false);
        //设置超时时间
        httpURLConnection.setConnectTimeout(1000);
        httpURLConnection.setReadTimeout(1000);
        return httpURLConnection.getInputStream();
    }

	// 递归删除文件夹及其文件
    private void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteFolder(file);
                } else {
                    file.delete();
                }
            }
        }
        folder.delete();
    }

小结

本篇文章 就是解决 在Java项目中实现资料包的导入读取并导出压缩包,加强文件读写的能力 冲!!!。

08-11 07:19