edit_xlsx/utils/
zip_util.rs1use std::{fs, io};
2use std::fs::File;
3use std::io::{Read, Write};
4use std::path::Path;
5use walkdir::WalkDir;
6use zip::CompressionMethod;
7use zip::result::ZipError;
8use zip::write::FileOptions;
9
10pub(crate) fn extract_dir<P: AsRef<Path>>(file_path: P, target: &str) -> zip::result::ZipResult<String> {
11 let file = File::open(&file_path)?;
13 let mut archive = zip::ZipArchive::new(file)?;
14 let base_path = Path::new(&target);
16 match fs::create_dir(&base_path) {
17 Err(why) => println!("! {:?}", why.kind()),
18 Ok(_) => {},
19 }
20 for i in 0..archive.len() {
21 let mut file = archive.by_index(i)?;
22 let out_path = match file.enclosed_name() {
23 Some(path) => path.to_owned(),
24 None => continue,
25 };
26 let out_path = &base_path.join(out_path);
27 {
28 let comment = file.comment();
29 if !comment.is_empty() {
30 println!("File {i} comment: {comment}");
31 }
32 }
33 if (*file.name()).ends_with('/') {
34 fs::create_dir_all(&out_path)?;
35 } else {
36 if let Some(p) = out_path.parent() {
37 if !p.exists() {
38 fs::create_dir_all(p)?;
39 }
40 }
41 let mut outfile = fs::File::create(&out_path)?;
42 io::copy(&mut file, &mut outfile)?;
43 }
44 #[cfg(unix)]
46 {
47 use std::os::unix::fs::PermissionsExt;
48
49 if let Some(mode) = file.unix_mode() {
50 fs::set_permissions(&out_path, fs::Permissions::from_mode(mode))?;
51 }
52 }
53 }
54 let tmp_dir = base_path.to_str().ok_or(ZipError::FileNotFound)?.to_string();
55 Ok(tmp_dir)
56}
57
58pub(crate) fn zip_dir<P: AsRef<Path>>(prefix: &str, file_path: P) -> zip::result::ZipResult<()> {
59 let writer = File::create(&file_path)?;
60 let walk_dir = WalkDir::new(&prefix);
61 let it = walk_dir.into_iter();
62 let it = &mut it.filter_map(|e| e.ok());
63
64 let mut zip = zip::ZipWriter::new(writer);
65 let options = FileOptions::default()
66 .compression_method(CompressionMethod::Deflated)
67 .unix_permissions(0o755);
68
69 let mut buffer = Vec::new();
70 for entry in it {
71 let path = entry.path();
72 let name = path.strip_prefix(Path::new(prefix)).unwrap();
73 if path.is_file() {
76 #[allow(deprecated)]
78 zip.start_file_from_path(name, options)?;
79 let mut f = File::open(path)?;
80
81 f.read_to_end(&mut buffer)?;
82 zip.write_all(&buffer)?;
83 buffer.clear();
84 } else if !name.as_os_str().is_empty() {
85 #[allow(deprecated)]
89 zip.add_directory_from_path(name, options)?;
90 }
91 }
92 zip.finish()?;
93 Ok(())
94}
95
96#[test]
97fn test() -> io::Result<()> {
98 let file = File::open("./examples/xlsx/accounting.xlsx")?;
99 let mut archive = zip::ZipArchive::new(file)?;
101 let file_path = "xl/styles.xml";
102
103 for i in 0..archive.len() {
104 let mut file = archive.by_index(i)?;
105 println!("{}", file.name());
106 if file.name() == file_path {
107 let mut contents = String::new();
108 file.read_to_string(&mut contents)?;
109 println!("File contents: {}", contents);
110 }
111 }
112 Ok(())
121}