Files
nx9-url-shortener/src/services/bulk.rs
T

50 lines
1.6 KiB
Rust

use crate::models::Url;
use crate::services::qr::{generate_qr_png, generate_qr_svg};
use std::io::Write;
use zip::write::FileOptions;
use zip::ZipWriter;
/// Export QR codes for the given URLs as a ZIP file.
/// `format` can be "png" or "svg".
/// `base_url` is used to build the full short URL encoded in the QR.
pub fn export_qr_zip(
urls: &[Url],
format: &str,
base_url: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut buf = Vec::new();
{
let mut zip = ZipWriter::new(std::io::Cursor::new(&mut buf));
let options =
FileOptions::<()>::default().compression_method(zip::CompressionMethod::Deflated);
let mut csv_content = String::from("code,destination,qr_filename\n");
for url in urls {
let full_url = format!("{}/{}", base_url.trim_end_matches('/'), url.code);
let ext = if format == "svg" { "svg" } else { "png" };
let filename = format!("{}.{}", url.code, ext);
let qr_data = if format == "svg" {
generate_qr_svg(&full_url)?.into_bytes()
} else {
generate_qr_png(&full_url, 256)?
};
zip.start_file(&filename, options)?;
zip.write_all(&qr_data)?;
// Escape quotes in destination for CSV formatting
let escaped_dest = url.destination.replace('"', "\"\"");
csv_content.push_str(&format!("{},\"{}\",{}\n", url.code, escaped_dest, filename));
}
zip.start_file("manifest.csv", options)?;
zip.write_all(csv_content.as_bytes())?;
zip.finish()?;
}
Ok(buf)
}