IDEMPIERE-3997 Attachment panel : ability to download all attachments as zip file. Base on patch from Nicolas Micoud.

This commit is contained in:
Heng Sin Low 2019-09-10 11:06:46 +08:00
parent 54aab6fea3
commit f4aca34b6e
4 changed files with 160 additions and 1 deletions

View File

@ -20,12 +20,19 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.taskdefs.Zip;
import org.compiere.tools.FileUtil;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
@ -633,4 +640,57 @@ public class MAttachment extends X_AD_Attachment
return attachid; return attachid;
} }
public File saveAsZip() {
if (getEntryCount() < 1) {
return null;
}
String name = MTable.get(Env.getCtx(), getAD_Table_ID()).getTableName() + "_" + getRecord_ID();
File tempfolder = null;
try {
Path tempPath = Files.createTempDirectory(name);
tempfolder = tempPath.toFile();
} catch (IOException e1) {
throw new AdempiereException("Unable to create temp folder", e1);
}
File destZipFile = null;
try {
destZipFile = File.createTempFile(name, ".zip");
} catch (Throwable e) {
throw new AdempiereException("Unable to create temp file", e);
}
destZipFile.delete();
MAttachmentEntry[] entries = getEntries();
MAttachmentEntry entry = null;
int index = 0;
for (int i = 0; i < entries.length; i++) {
entry = entries[i];
index = i;
File destinationFile = new File(tempfolder, entry.getName());
FileUtil.copy(this, destinationFile, index);
}
Zip zipper = new Zip();
zipper.setDestFile(destZipFile);
zipper.setBasedir(tempfolder);
zipper.setUpdate(true);
zipper.setCompress(true);
zipper.setCaseSensitive(false);
zipper.setFilesonly(true);
zipper.setTaskName("zip");
zipper.setTaskType("zip");
zipper.setProject(new Project());
zipper.setOwningTarget(new Target());
zipper.execute();
try {
FileUtil.deleteDirectory(tempfolder);
} catch (IOException e) {}
return destZipFile;
}
} // MAttachment } // MAttachment

View File

@ -20,13 +20,21 @@ import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MAttachment;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Util; import org.compiere.util.Util;
@ -429,6 +437,13 @@ public class FileUtil
return localFile; return localFile;
} }
/**
*
* @param path
* @return true if deleted
* @throws FileNotFoundException
* @Deprecated
*/
public static boolean deleteFolderRecursive(File path) throws FileNotFoundException { public static boolean deleteFolderRecursive(File path) throws FileNotFoundException {
if (!path.exists()) if (!path.exists())
throw new FileNotFoundException(path.getAbsolutePath()); throw new FileNotFoundException(path.getAbsolutePath());
@ -441,4 +456,55 @@ public class FileUtil
return ret && path.delete(); return ret && path.delete();
} }
/**
* copy attachment entry to file
* @param attachment
* @param destinationFile
* @param index
*/
public static void copy(MAttachment attachment, File destinationFile, int index)
{
FileOutputStream destinationFileOutputStream=null;
try {
destinationFile.createNewFile();
destinationFileOutputStream = new FileOutputStream(destinationFile);
byte[] buffer = attachment.getEntryData(index);
destinationFileOutputStream.write(buffer);
}
catch( java.io.FileNotFoundException f ) {
throw new AdempiereException("File not found exception : " + destinationFile.getName() + " : " + f);
}
catch( java.io.IOException e ) {
throw new AdempiereException("IOException : " + e);
} finally {
try {
if (destinationFileOutputStream != null)
destinationFileOutputStream.close();
} catch(Exception e) {
throw new AdempiereException("Exception : " + e);
}
}
}
/**
* delete folder recursively
* @param folder
* @throws IOException
*/
public static void deleteDirectory(File folder) throws IOException {
Path directory = folder.toPath();
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
}
} // FileUtil } // FileUtil

View File

@ -17,6 +17,7 @@
package org.adempiere.webui.panel; package org.adempiere.webui.panel;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -25,6 +26,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.util.Callback; import org.adempiere.util.Callback;
import org.adempiere.webui.AdempiereWebUI; import org.adempiere.webui.AdempiereWebUI;
import org.adempiere.webui.ClientInfo; import org.adempiere.webui.ClientInfo;
@ -44,6 +46,7 @@ import org.adempiere.webui.util.ZKUpdateUtil;
import org.adempiere.webui.window.FDialog; import org.adempiere.webui.window.FDialog;
import org.compiere.model.MAttachment; import org.compiere.model.MAttachment;
import org.compiere.model.MAttachmentEntry; import org.compiere.model.MAttachmentEntry;
import org.compiere.model.MTable;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
@ -76,7 +79,7 @@ public class WAttachment extends Window implements EventListener<Event>
/** /**
* *
*/ */
private static final long serialVersionUID = 4311076973993361653L; private static final long serialVersionUID = 8266807399792500541L;
private static CLogger log = CLogger.getCLogger(WAttachment.class); private static CLogger log = CLogger.getCLogger(WAttachment.class);
@ -99,6 +102,7 @@ public class WAttachment extends Window implements EventListener<Event>
private Button bDelete = ButtonFactory.createNamedButton(ConfirmPanel.A_DELETE, false, true); private Button bDelete = ButtonFactory.createNamedButton(ConfirmPanel.A_DELETE, false, true);
private Button bSave = new Button(); private Button bSave = new Button();
private Button bSaveAllAsZip = new Button();
private Button bDeleteAll = new Button(); private Button bDeleteAll = new Button();
private Button bLoad = new Button(); private Button bLoad = new Button();
private Button bCancel = ButtonFactory.createNamedButton(ConfirmPanel.A_CANCEL, false, true); private Button bCancel = ButtonFactory.createNamedButton(ConfirmPanel.A_CANCEL, false, true);
@ -259,6 +263,7 @@ public class WAttachment extends Window implements EventListener<Event>
toolBar.appendChild(bLoad); toolBar.appendChild(bLoad);
toolBar.appendChild(bDelete); toolBar.appendChild(bDelete);
toolBar.appendChild(bSave); toolBar.appendChild(bSave);
toolBar.appendChild(bSaveAllAsZip);
toolBar.appendChild(cbContent); toolBar.appendChild(cbContent);
toolBar.appendChild(sizeLabel); toolBar.appendChild(sizeLabel);
@ -281,6 +286,15 @@ public class WAttachment extends Window implements EventListener<Event>
bSave.setTooltiptext(Msg.getMsg(Env.getCtx(), "AttachmentSave")); bSave.setTooltiptext(Msg.getMsg(Env.getCtx(), "AttachmentSave"));
bSave.addEventListener(Events.ON_CLICK, this); bSave.addEventListener(Events.ON_CLICK, this);
bSaveAllAsZip.setEnabled(false);
bSaveAllAsZip.setSclass("img-btn");
if (ThemeManager.isUseFontIconForImage())
bSaveAllAsZip.setIconSclass("z-icon-file-zip-o");
else
bSaveAllAsZip.setImage(ThemeManager.getThemeResource("images/SaveAsZip24.png"));
bSaveAllAsZip.setTooltiptext(Msg.getMsg(Env.getCtx(), "ExportZIP"));
bSaveAllAsZip.addEventListener(Events.ON_CLICK, this);
if (ThemeManager.isUseFontIconForImage()) if (ThemeManager.isUseFontIconForImage())
bLoad.setIconSclass("z-icon-Import"); bLoad.setIconSclass("z-icon-Import");
else else
@ -420,6 +434,7 @@ public class WAttachment extends Window implements EventListener<Event>
sizeLabel.setText(size.toPlainString() + unit); sizeLabel.setText(size.toPlainString() + unit);
bSave.setEnabled(true); bSave.setEnabled(true);
bSaveAllAsZip.setEnabled(true);
bDelete.setEnabled(true); bDelete.setEnabled(true);
if (autoPreviewList.contains(mimeType)) if (autoPreviewList.contains(mimeType))
@ -436,6 +451,7 @@ public class WAttachment extends Window implements EventListener<Event>
else else
{ {
bSave.setEnabled(false); bSave.setEnabled(false);
bSaveAllAsZip.setEnabled(false);
bDelete.setEnabled(false); bDelete.setEnabled(false);
sizeLabel.setText(""); sizeLabel.setText("");
return false; return false;
@ -572,6 +588,8 @@ public class WAttachment extends Window implements EventListener<Event>
saveAttachmentToFile(); saveAttachmentToFile();
} else if (e.getTarget() == bRefresh) { } else if (e.getTarget() == bRefresh) {
displayData(cbContent.getSelectedIndex(), true); displayData(cbContent.getSelectedIndex(), true);
} else if (e.getTarget() == bSaveAllAsZip) {
saveAllAsZip();
} }
} // onEvent } // onEvent
@ -734,4 +752,19 @@ public class WAttachment extends Window implements EventListener<Event>
} }
return "UTF-8"; return "UTF-8";
} }
private void saveAllAsZip() {
File zipFile = m_attachment.saveAsZip();
if (zipFile != null) {
String name = MTable.get(Env.getCtx(), m_attachment.getAD_Table_ID()).getTableName() + "_" + m_attachment.getRecord_ID();
AMedia media = null;
try {
media = new AMedia(name, null, "application/zip", zipFile, true);
} catch (Exception e) {
throw new AdempiereException("Error when converting zip file to media : " + e);
}
Filedownload.save(media);
}
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB