Zip Up and Save Space
When you have a database which stores a lot of unzipped attachments, wouldn't it be nice if you could have an agent which periodically runs over them and zips them all? Sure could save a lot of space.
Well, you can and it's not even that difficult. The nice thing is you don't even need Winzip or any other tools to do it, it's already built into the Domino server and client! The magic word is "Java". Java has built in classes for zipping and unzipping files, which we are going to use for this small agent. There is just one small caveat: it only runs on R5.03 servers and above.
First, some things you need to make sure you have so as to get this example up and running:
Create a database, and in that database create a form. Call it whatever you want. On the form, create a rich text field called "Body" (you can call it something else, but then you'll have to modify the agent code below). Also create a view that shows these documents. Now create an agent which should run manually from the actions menu on selected documents.
Copy and paste the code below in to the agent. Don't get scared if it doesn't make a whole lot of sense. There are plenty of comments in the .Java file you can download here - ZipUp.java
// Written by Erwin van Hunen
//
// In this example the agent is run manually from the actions menu on selected documents,
// but of course it would make much more sense to run it as a scheduled or triggered agent
// in the background
import lotus.domino.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
FileOutputStream fos;
Item item;
RichTextItem rtitem;
String attachmentname;
Vector items;
String archivename;
byte b[] = new byte[512];
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
Database db = agentContext.getCurrentDatabase();
DocumentCollection col = agentContext.getUnprocessedDocuments();
Document doc = col.getFirstDocument();
while (doc != null)
{
archivename = session.getEnvironmentString("Directory",true) + "\\" + doc.getNoteID() + ".zip";
fos = new FileOutputStream(archivename);
ZipOutputStream zout = new ZipOutputStream(fos);
rtitem = (RichTextItem) doc.getFirstItem("Body");
items = doc.getItems();
for (int i=0; i<items.size(); i++) {
item = (Item) items.elementAt(i);
if(item.getType() == Item.ATTACHMENT)
{
if (item.getValueString().length() != 0)
{
attachmentname = item.getValueString();
EmbeddedObject attachment = (EmbeddedObject) doc.getAttachment(attachmentname);
InputStream in = attachment.getInputStream();
ZipEntry e = new ZipEntry(attachment.getName().replace(File.separatorChar,'/'));
zout.putNextEntry(e);
int len=0;
while((len=in.read(b)) != -1)
{
zout.write(b,0,len);
}
zout.closeEntry();
attachment.remove();
}
}
}
zout.close();
fos.close();
doc.replaceItemValue("Body","");
rtitem.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, archivename, archivename);
doc.save(true);
File zipfile = new File(archivename);
zipfile.delete();
doc = col.getNextDocument(doc);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Trying the agent:
Create a document in the database and attach some files in the body field. Save the document, close it, select it in the view and run the agent from the actions menu. When the agent finishes, open the document and you should see a zip file instead of your attachments.
Basically this is what happens when you run the agent:
Domino creates an empty zipfile in the Notes\Data directory which is named after the NoteID of the document. Then it loops through all the attachments on the document and add them to the zipfile. Finally, it deletes the attachments from the document and attaches the zipfile to the document.
I can think of a lot of improvements, like setting a flag which means that the attachments already have been zipped, having a user editable field for the zipfilename, or using the date for the zipfilename, or what about an online zipper? Just provide the user with a form on which he can upload a file, have an agent zip the attachment and present the zipped file?
All in all very straightforward I would say! No need for external libraries, tools, etc. It's all done with built-in functionality of the Domino server and the Notes client. Isn't this the reason why we all love Domino?
Jake's Comments:
Thanks Erwin. Great write up.
You may all have noticed that this isn't really a Domino based solution. When we have a web based application the attachments are rarely in the Body field. This is not to say that it can't be made in to one though, as Erwin mentions. The reason I decided to publish Erwin's article is that it is such good food for thought.
I've placed the code in a file you can download from the top left of the page, to make life easier.
About the Author:
Erwin van Hunen is from The Netherlands and currently works as a Lotus Domino Application Architect for Inter Access B.V.
Confused
Hmm...
Doesn't Notes have a compression function? Why would I do this?
Reply
Re: Confused
Actually I can come up with at least one reason: say you want to give users the option to upload a set of word documents, which should be made available as a zip file for download.
This agent can make the zip file without bothering the uploader to create the zip file etc. etc.
Reply
Show the rest of this thread
Re: Confused
The compression function of Notes when you attach a file is quite ineficiente.
Compare when you attach a file with compression active, without compression, to the size of the file if zipped and you'll see from yourself.
FP (France)
Reply
Saves bandwidth...
When Domino serves up a Domino-compressed attachment, it first decompresses it, then sends it over the wire. But a zip file stays compressed, making for a smaller download.
The user saves download time, you save money on bandwidth. Everyone's happy!
Sean
Reply
How can I remove the icon
Hi
I found the code very usefull but I don't like the deletion of the content of the body field. So I remove that part. But unfortunately, the attachment icon is (although the attachment has been removed) still visible. What can I do to remove the icon?
Regards Chris
Reply
Re: How can I remove the icon
That was exactly my problem, which is the only reason I remove the contents of the body field...
Reply
Show the rest of this thread
Cannot View Files
Although this works very well to ZIP files, if you click on the attached ZIP file and choose view, you cannot preview the files within the ZIP file. It displays the following error: "Sorry, the program encountered a problem and cannot view the document"
Normally, you can do this.
Any ideas?
Reply
Re: Cannot View Files
I've test this on a R5 client and an N6 client. The R5 client viewer worked fine. The N6 client gave the error you describe. Didn't find anything in the fixlist for this, but will call support, because this definitely looks like a useful tool.
Reply
Show the rest of this thread
Re: Cannot View Files
Hi, did you find a solution? Still using that agent? I would like to share your experiences with that tool.
Reply
Zipping an attachment while sending a mail
Hi,
Can this feature be used in Lotus Script also?
I am trying to send a mail with zipped attachment to save space in recipient's mail box.
TIA, Albina
Reply
can you make this work on domino?
As Jake said, this isn't really a domino solution since the attachments aren't in the body field. Can you make this work on a domino db where the attachments are uploaded via file upload control?
What is the difference between this and the other product mentioned - zipmail?
Thanks!!! :-)
Reply
<> What about the other way?
Has anyone got any examples of taking a zip file and automatically unzipping it?
Is there any help available on these methods?
TIA
Malc.
Reply
Re: <> What about the other way?
hey malc, I am also facing the same problem.have u got any solution for unzipping the zipped attachments.
Thanks in Advance Ashish Kr.Srivastava
Reply
Show the rest of this thread
Problem with Zipping the content of directory and
hello i m nikhil. i m trying to zip the contents of directory and the file which are in the sub directory .i have used java.util.zip. Programmes run without any error but when i open the newly zip file it only list the contents of files in the directory but programmes doesnt zip the subdirectory
thnks nikhil below there is a code import java.util.*; import java.io.*; import java.util.zip.*; class DirTest { public void filePath(String strFilename) { String s[]=new String[0]; ArrayList arr=new ArrayList(); try { File f=new File(strFilename); if(f.isDirectory()) { s=f.list(); } for(int i=0;i<s.length;i++) { File f1=new File(f.getPath()+"/"+ s[i]); if(f1.isDirectory()) { filePath(f1.getPath()); } else { arr.add(f1.getPath()); } } arrListing(arr); } catch(Exception e) { System.out.println(e.getMessage()); } } public void arrListing(ArrayList a1) { try { FileOutputStream fout=new FileOutputStream("C:/myDir/ot.zip"); ZipOutputStream zout=new ZipOutputStream(fout); FileInputStream fin=null; Iterator itr=a1.iterator(); while(itr.hasNext()) { String str=(String) itr.next(); System.out.println(str); zout.setMethod(ZipOutputStream.DEFLATED); zout.setLevel(9); zout.putNextEntry(new ZipEntry(str)); fin=new FileInputStream(str); int c; while((c=fin.read())!=-1) { zout.write(c); } zout.flush(); }
fin.close(); zout.closeEntry(); zout.close(); } catch(Exception e) { System.out.println(e); } } public static void main(String args[]) throws IOException { DirTest objDir=new DirTest(); objDir.filePath("C:/myDir"); } }
Reply