10 changed files with 14279 additions and 1 deletions
@ -0,0 +1,264 @@ |
|||||
|
package org.dromara.business.utils; |
||||
|
|
||||
|
|
||||
|
import cn.hutool.extra.spring.SpringUtil; |
||||
|
import com.spire.doc.Document; |
||||
|
import com.spire.doc.FileFormat; |
||||
|
import freemarker.template.Template; |
||||
|
import jakarta.servlet.http.HttpServletResponse; |
||||
|
import org.springframework.core.io.ByteArrayResource; |
||||
|
import org.springframework.core.io.InputStreamSource; |
||||
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; |
||||
|
|
||||
|
import java.io.*; |
||||
|
import java.net.HttpURLConnection; |
||||
|
import java.net.URL; |
||||
|
import java.net.URLEncoder; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.Base64; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
public class FreemarkerUtil { |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Freemarker的配置类,模板目录默认 在 resources下的 templates |
||||
|
*/ |
||||
|
private static FreeMarkerConfigurer freeMarkerConfigurer = SpringUtil.getBean(FreeMarkerConfigurer.class); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 将模板文件填充数据后转为String |
||||
|
* |
||||
|
* @param templateName ftl模板文件名 |
||||
|
* @param datas 数据集合 |
||||
|
* @return |
||||
|
*/ |
||||
|
public static String renderTplFileToStr(String templateName, Map<String, Object> datas) { |
||||
|
|
||||
|
try { |
||||
|
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8"); |
||||
|
|
||||
|
|
||||
|
StringWriter out = new StringWriter(); |
||||
|
|
||||
|
template.process(datas, out); |
||||
|
|
||||
|
out.flush(); |
||||
|
out.close(); |
||||
|
return out.getBuffer().toString(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 将模板文件填充数据后导出为文件(导出html,word文件都使用此方法) |
||||
|
* |
||||
|
* @param templateName ftl模板文件名 |
||||
|
* @param datas 数据集合 |
||||
|
* @param outFile 导出的文件路径名称 |
||||
|
*/ |
||||
|
public static void renderTplFileToLocalFile(String templateName, Map<String, Object> datas, ByteArrayOutputStream fos) { |
||||
|
|
||||
|
Writer out = null; |
||||
|
|
||||
|
OutputStreamWriter oWriter = null; |
||||
|
try { |
||||
|
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8"); |
||||
|
oWriter = new OutputStreamWriter(fos, "UTF-8"); |
||||
|
// 这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
|
||||
|
out = new BufferedWriter(new OutputStreamWriter(fos)); |
||||
|
out = new BufferedWriter(oWriter); |
||||
|
template.process(datas, out); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} finally { |
||||
|
try { |
||||
|
if (oWriter != null) { |
||||
|
oWriter.close(); |
||||
|
} |
||||
|
if (fos != null) { |
||||
|
fos.close(); |
||||
|
} |
||||
|
if (out != null) { |
||||
|
out.close(); |
||||
|
} |
||||
|
} catch (IOException ioException) { |
||||
|
ioException.printStackTrace(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 根据word模板获取输入流 |
||||
|
* |
||||
|
* @param templateName |
||||
|
* @param datas |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static InputStream renderTplFileToWordInputStream(String templateName, Map<String, Object> datas) throws IOException { |
||||
|
Document doc = null; |
||||
|
DataInputStream in = null; |
||||
|
try { |
||||
|
in = renderTplFileToIOFile(templateName, datas); |
||||
|
doc = new Document(); |
||||
|
doc.loadFromStream(in, FileFormat.Auto); |
||||
|
|
||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
|
doc.saveToStream(baos, FileFormat.Docx); |
||||
|
|
||||
|
ByteArrayOutputStream byteArrayOutputStream = ZipStreamUtil.copyStream(baos); |
||||
|
//输出流转为输入流
|
||||
|
InputStreamSource inputStreamSource = new ByteArrayResource(byteArrayOutputStream.toByteArray()); |
||||
|
return inputStreamSource.getInputStream(); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} finally { |
||||
|
if (in != null) { |
||||
|
in.close(); |
||||
|
} |
||||
|
if (doc != null) { |
||||
|
doc.close(); |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 将模板文件填充数据后返回文件流 |
||||
|
* |
||||
|
* @param templateName ftl模板文件名 |
||||
|
* @param datas 数据集合 |
||||
|
*/ |
||||
|
public static DataInputStream renderTplFileToIOFile(String templateName, Map<String, Object> datas) throws Exception { |
||||
|
ByteArrayInputStream in = null; |
||||
|
Writer out = null; |
||||
|
try { |
||||
|
Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName, "UTF-8"); |
||||
|
out = new StringWriter(); |
||||
|
template.process(datas, out); |
||||
|
String out1 = out.toString().replace("&", "&");//替换非法字符
|
||||
|
in = new ByteArrayInputStream(out1.getBytes("UTF-8")); |
||||
|
return new DataInputStream(in); |
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} finally { |
||||
|
if (out != null) { |
||||
|
out.close(); |
||||
|
} |
||||
|
if (in != null) { |
||||
|
in.close(); |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 根据word模板获取输入流 |
||||
|
* |
||||
|
* @param templateName |
||||
|
* @param datas |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static void renderTplFileToWord(String documentName , String templateName, Map<String, Object> datas, HttpServletResponse response) throws IOException { |
||||
|
response.setContentType("application/x-msdownload;"); |
||||
|
response.setHeader("Content-disposition", "attachment; filename=" + documentName); |
||||
|
Document doc = null; |
||||
|
DataInputStream in = null; |
||||
|
try { |
||||
|
in = renderTplFileToIOFile(templateName, datas); |
||||
|
doc = new Document(); |
||||
|
doc.loadFromStream(in, FileFormat.Auto); |
||||
|
|
||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
|
doc.saveToStream(baos, FileFormat.Docx); |
||||
|
|
||||
|
ByteArrayOutputStream byteArrayOutputStream = ZipStreamUtil.copyStream(baos); |
||||
|
// 将生成的文档写入到响应的输出流中
|
||||
|
response.reset(); // 重置响应
|
||||
|
response.getOutputStream().write(byteArrayOutputStream.toByteArray()); |
||||
|
response.getOutputStream().flush(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} finally { |
||||
|
if (in != null) { |
||||
|
in.close(); |
||||
|
} |
||||
|
if (doc != null) { |
||||
|
doc.close(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 根据word模板获取输入流 |
||||
|
* |
||||
|
* @param templateName |
||||
|
* @param datas |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static void renderTplFileToPDF(String fileName ,String templateName, Map<String, Object> datas,HttpServletResponse response) throws IOException { |
||||
|
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 字符集编码
|
||||
|
response.setContentType("application/pdf;"); |
||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")); |
||||
|
response.addHeader("Access-Control-Allow-Origin", "*"); // 实现跨域
|
||||
|
Document doc = null; |
||||
|
DataInputStream in = null; |
||||
|
try { |
||||
|
in = renderTplFileToIOFile(templateName, datas); |
||||
|
doc = new Document(); |
||||
|
doc.loadFromStream(in, FileFormat.Auto); |
||||
|
|
||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||
|
doc.saveToStream(baos, FileFormat.PDF); |
||||
|
|
||||
|
// 将生成的文档写入到响应的输出流中
|
||||
|
response.reset(); // 重置响应
|
||||
|
response.getOutputStream().write(baos.toByteArray()); |
||||
|
response.getOutputStream().flush(); |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public static String encodeImageToBase64(String imageUrl) throws Exception { |
||||
|
URL url = new URL(imageUrl); |
||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); |
||||
|
connection.setRequestMethod("GET"); |
||||
|
|
||||
|
try (InputStream in = connection.getInputStream(); |
||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream()) { |
||||
|
byte[] buffer = new byte[1024]; |
||||
|
int bytesRead; |
||||
|
while ((bytesRead = in.read(buffer)) != -1) { |
||||
|
baos.write(buffer, 0, bytesRead); |
||||
|
} |
||||
|
byte[] imageBytes = baos.toByteArray(); |
||||
|
return Base64.getEncoder().encodeToString(imageBytes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
@ -0,0 +1,283 @@ |
|||||
|
package org.dromara.business.utils; |
||||
|
|
||||
|
import java.io.*; |
||||
|
import java.net.MalformedURLException; |
||||
|
import java.net.URL; |
||||
|
import java.nio.file.Files; |
||||
|
import java.util.function.BiFunction; |
||||
|
import java.util.zip.ZipEntry; |
||||
|
import java.util.zip.ZipInputStream; |
||||
|
import java.util.zip.ZipOutputStream; |
||||
|
|
||||
|
import static java.util.zip.ZipEntry.STORED; |
||||
|
import static java.util.zip.ZipOutputStream.DEFLATED; |
||||
|
|
||||
|
public class ZipStreamUtil { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
/* String srcPath = "E:\\360极速浏览器下载\\Linksla生产 (1).docx"; |
||||
|
String outPath = "E:\\360极速浏览器下载\\Linksla生产2.docx"; |
||||
|
try (FileInputStream is = new FileInputStream(srcPath)) { |
||||
|
try (FileOutputStream os = new FileOutputStream(outPath)) { |
||||
|
ZipStreamUtil.zipEntryCopyStream(os, is, new BiFunction<ZipEntry, ZipInputStream, byte[]>() { |
||||
|
@Override |
||||
|
public byte[] apply(ZipEntry se, ZipInputStream zis) { |
||||
|
byte[] rt = null; |
||||
|
String name = se.getName(); |
||||
|
if (null == name) return rt; |
||||
|
String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)", |
||||
|
se.getName(), (se.isDirectory()) ? 1 : 0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment()); |
||||
|
System.out.println(line); |
||||
|
if (name.endsWith("word/document.xml")) { |
||||
|
try { |
||||
|
byte[] oldBytes = ZipStreamUtil.toByteArray(zis); |
||||
|
String str = (new String(oldBytes)); |
||||
|
String appendString = str.replace("Evaluation Warning: The document was created with Spire.Doc for JAVA.", ""); |
||||
|
//rt = str.getBytes();
|
||||
|
// 为了避免多余的编码转换, 改成下面的代码更好.
|
||||
|
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) { |
||||
|
//ZipStreamUtil.copyStream(buf, zis);
|
||||
|
buf.write(appendString.getBytes()); |
||||
|
rt = buf.toByteArray(); |
||||
|
} |
||||
|
} catch (IOException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
return rt; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} catch (FileNotFoundException e) { |
||||
|
e.printStackTrace(); |
||||
|
} catch (IOException e) { |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
System.out.println("ZipTxtAppendTest done." + outPath);*/ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 过滤word 水印 |
||||
|
* |
||||
|
* @param baos |
||||
|
* @return |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static ByteArrayOutputStream copyStream(ByteArrayOutputStream baos) throws IOException { |
||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); |
||||
|
|
||||
|
ByteArrayOutputStream baoss = new ByteArrayOutputStream(); |
||||
|
try { |
||||
|
|
||||
|
ZipStreamUtil.zipEntryCopyStream(baoss, bais, new BiFunction<ZipEntry, ZipInputStream, byte[]>() { |
||||
|
@Override |
||||
|
public byte[] apply(ZipEntry se, ZipInputStream zis) { |
||||
|
byte[] rt = null; |
||||
|
String name = se.getName(); |
||||
|
if (null == name) return rt; |
||||
|
String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)", |
||||
|
se.getName(), (se.isDirectory()) ? 1 : 0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment()); |
||||
|
System.out.println(line); |
||||
|
if (name.endsWith("word/document.xml")) { |
||||
|
try { |
||||
|
byte[] oldBytes = ZipStreamUtil.toByteArray(zis); |
||||
|
String str = (new String(oldBytes)); |
||||
|
String appendString = str.replace("Evaluation Warning: The document was created with Spire.Doc for JAVA.", ""); |
||||
|
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) { |
||||
|
buf.write(appendString.getBytes()); |
||||
|
rt = buf.toByteArray(); |
||||
|
} |
||||
|
} catch (IOException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
} |
||||
|
return rt; |
||||
|
} |
||||
|
}); |
||||
|
} finally { |
||||
|
bais.close(); |
||||
|
baoss.close(); |
||||
|
} |
||||
|
|
||||
|
return baoss; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public static byte[] toByteArray(InputStream in) throws IOException { |
||||
|
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { |
||||
|
copyStream(out, in); |
||||
|
return out.toByteArray(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void copyStream(OutputStream os, InputStream is) throws IOException { |
||||
|
copyStream(os, is, 0); |
||||
|
} |
||||
|
public static void copyStream(OutputStream os, InputStream is, int bufsize) throws IOException { |
||||
|
if (bufsize <= 0) bufsize = 4096; |
||||
|
int len; |
||||
|
byte[] bytes = new byte[bufsize]; |
||||
|
while ((len = is.read(bytes)) != -1) { |
||||
|
os.write(bytes, 0, len); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 基于ZIP项目的复制Zip流. |
||||
|
* |
||||
|
* @param dst The output stream of the destination zip. |
||||
|
* @param src Source zip. |
||||
|
* @param transform 转换处理. 可以为null, 不转换. 该回调函数的原型为`byte[] transform(ZipEntry zipEntry, ZipInputStream zis)`, 当返回值为 null时保留原值, 为非null时用返回值替换当前ZipEntry对应的流数据. |
||||
|
* @return 返回转换次数. |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static int zipEntryCopyStreamZip(ZipOutputStream zos, ZipInputStream zis, BiFunction<ZipEntry, ZipInputStream, byte[]> transform) throws IOException { |
||||
|
int rt = 0; |
||||
|
ZipEntry se; |
||||
|
while ((se = zis.getNextEntry()) != null) { |
||||
|
if (null == se) continue; |
||||
|
//String line = String.format("ZipEntry(%s, isDirectory=%d, size=%d, compressedSize=%d, time=%d, crc=%d, method=%d, comment=%s)",
|
||||
|
// se.getName(), (se.isDirectory())?1:0, se.getSize(), se.getCompressedSize(), se.getTime(), se.getCrc(), se.getMethod(), se.getComment());
|
||||
|
//System.out.println(line);
|
||||
|
byte[] dstBytes = null; |
||||
|
if (null != transform) { |
||||
|
dstBytes = transform.apply(se, zis); |
||||
|
} |
||||
|
// choose by dstBytes.
|
||||
|
if (null == dstBytes) { |
||||
|
ZipEntry de = new ZipEntry(se); |
||||
|
de.setCompressedSize(-1); // 重新压缩后, csize 可能不一致, 故需要恢复为默认值.
|
||||
|
zos.putNextEntry(de); |
||||
|
copyStream(zos, zis); |
||||
|
zos.closeEntry(); |
||||
|
} else { |
||||
|
++rt; |
||||
|
//ZipEntry de = new ZipEntry(se);
|
||||
|
//de.setCompressedSize(-1);
|
||||
|
//de.setCrc(-1);
|
||||
|
// == fix IllegalArgumentException.
|
||||
|
ZipEntry de = new ZipEntry(se.getName()); |
||||
|
//System.out.println(se.getTime());
|
||||
|
//final long timeNone = 312739200000L;
|
||||
|
//if (timeNone!=se.getTime() && null!=se.getLastModifiedTime()) { // 发现会被自动改为当前时间.
|
||||
|
if (null != se.getLastModifiedTime()) { |
||||
|
de.setLastModifiedTime(se.getLastModifiedTime()); |
||||
|
} |
||||
|
if (null != se.getLastAccessTime()) { |
||||
|
de.setLastAccessTime(se.getLastAccessTime()); |
||||
|
} |
||||
|
if (null != se.getCreationTime()) { |
||||
|
de.setCreationTime(se.getCreationTime()); |
||||
|
} |
||||
|
de.setSize(dstBytes.length); |
||||
|
//de.setCompressedSize(se.getCompressedSize()); // changed.
|
||||
|
//de.setCrc(se.getCrc()); // changed.
|
||||
|
int method = se.getMethod(); |
||||
|
if (method != STORED && method != DEFLATED) { |
||||
|
// No setMethod .
|
||||
|
} else { |
||||
|
de.setMethod(method); |
||||
|
} |
||||
|
de.setExtra(se.getExtra()); |
||||
|
de.setComment(se.getComment()); |
||||
|
zos.putNextEntry(de); |
||||
|
zos.write(dstBytes); |
||||
|
zos.closeEntry(); |
||||
|
} |
||||
|
} |
||||
|
return rt; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 基于ZIP项目的复制流. |
||||
|
* |
||||
|
* @param dst The output stream of the destination zip. |
||||
|
* @param src Source zip. |
||||
|
* @param transform 转换处理. 可以为null, 不转换. 该回调函数的原型为`byte[] transform(ZipEntry zipEntry, ZipInputStream zis)`, 当返回值为 null时保留原值, 为非null时用返回值替换当前ZipEntry对应的流数据. |
||||
|
* @return 返回转换次数. |
||||
|
* @throws IOException |
||||
|
*/ |
||||
|
public static int zipEntryCopyStream(OutputStream os, InputStream is, BiFunction<ZipEntry, ZipInputStream, byte[]> transform) throws IOException { |
||||
|
try (ZipInputStream zis = new ZipInputStream(is)) { |
||||
|
try (ZipOutputStream zos = new ZipOutputStream(os)) { |
||||
|
return zipEntryCopyStreamZip(zos, zis, transform); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void saveImageToFile(String imageUrl, File destination) throws IOException { |
||||
|
try (InputStream in = new URL(imageUrl).openStream()) { |
||||
|
Files.copy(in, destination.toPath()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void addFolderToZip(File sourceFolder, String baseFolderName, ZipOutputStream zos) throws IOException { |
||||
|
for (File file : sourceFolder.listFiles()) { |
||||
|
if (file.isDirectory()) { |
||||
|
addFolderToZip(file, baseFolderName + "/" + file.getName(), zos); |
||||
|
} else { |
||||
|
try (InputStream in = Files.newInputStream(file.toPath())) { |
||||
|
ZipEntry zipEntry = new ZipEntry(baseFolderName + "/" + file.getName()); |
||||
|
zos.putNextEntry(zipEntry); |
||||
|
byte[] buffer = new byte[1024]; |
||||
|
int length; |
||||
|
while ((length = in.read(buffer)) >= 0) { |
||||
|
zos.write(buffer, 0, length); |
||||
|
} |
||||
|
zos.closeEntry(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void deleteDirectory(File directory) { |
||||
|
for (File file : directory.listFiles()) { |
||||
|
if (file.isDirectory()) { |
||||
|
deleteDirectory(file); |
||||
|
} |
||||
|
file.delete(); |
||||
|
} |
||||
|
directory.delete(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
// Helper method to add image to zip stream
|
||||
|
public static void addImageToZip(String imageUrl, File targetFile, String folderName, ZipOutputStream zos) throws IOException { |
||||
|
if (imageUrl == null || imageUrl.isEmpty()) { |
||||
|
throw new IllegalArgumentException("The image URL cannot be null or empty."); |
||||
|
} |
||||
|
|
||||
|
URL url; |
||||
|
try { |
||||
|
url = new URL(imageUrl); |
||||
|
} catch (MalformedURLException e) { |
||||
|
throw new IOException("Invalid URL format: " + imageUrl, e); |
||||
|
} |
||||
|
|
||||
|
try (InputStream imageStream = url.openStream()) { |
||||
|
// Create zip entry for image
|
||||
|
String zipEntryName = folderName + "/" + targetFile.getName(); |
||||
|
ZipEntry zipEntry = new ZipEntry(zipEntryName); |
||||
|
zos.putNextEntry(zipEntry); |
||||
|
|
||||
|
// Write image content to zip stream
|
||||
|
byte[] buffer = new byte[8192]; // 8KB buffer for optimal performance
|
||||
|
int bytesRead; |
||||
|
while ((bytesRead = imageStream.read(buffer)) != -1) { |
||||
|
zos.write(buffer, 0, bytesRead); |
||||
|
} |
||||
|
|
||||
|
zos.closeEntry(); |
||||
|
} catch (IOException e) { |
||||
|
// Log the error and rethrow the exception for higher-level handling
|
||||
|
System.err.println("Error processing image from URL: " + imageUrl); |
||||
|
e.printStackTrace(); |
||||
|
throw e; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
File diff suppressed because it is too large
Loading…
Reference in new issue