You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Stephen Huey <st...@gmail.com> on 2010/01/05 23:27:54 UTC

Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

For posterity's sake, I meant to come back here and post the solution a
while ago.  I've got the full story here in this blog post:

http://stephenhuey.wordpress.com/2010/01/01/docxgae/

The relatively new Microsoft Office formats ending with extensions such as
.docx and .xlsx are zip files of directories of text files (XML) and images.
 Tried-and-true Java libraries for writing the old binary Microsoft Word and
Excel formats aren't yet supported on Google App Engine, so I was glad to
get this working since it was a required feature for our application.

My modified code for the zipDir and addDir methods is below.  As you can
see, I'm closing the ZipOutputStream rather than the OutputStream:


+ + + + + + + + + + + + + + + + + + + +


import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;

public class FileObjectHelper {

 public static FileObject createFolder(FileSystemManager fsManager, String
absolutePath) throws FileSystemException {
 FileObject theFolder = fsManager.resolveFile( absolutePath );
 if ( theFolder.exists() == false) {
 theFolder.createFolder();
 }
 return theFolder;
 }

 public static FileObject createFile(FileSystemManager fsManager, String
absolutePath) throws FileSystemException {
 FileObject theFile = fsManager.resolveFile( absolutePath );
 if ( theFile.exists() == false) {
 theFile.createFile();
 }
 return theFile;
 }

 public static void zipDir(FileObject docxZipFile, FileObject
directoryToZip) throws IOException {
 OutputStream out = docxZipFile.getContent().getOutputStream();
 ZipOutputStream zout = new ZipOutputStream(out);
 addDir(directoryToZip, zout, "");
 zout.close(); // make sure you close the ZipOutputStream, not the
OutputStream!
 }

 public static void addDir(FileObject dirObj, ZipOutputStream zout, String
basePathSoFar) throws IOException {
 FileObject[] files = dirObj.getChildren();
 byte[] tmpBuf = new byte[1024];

 for (int i = 0; i < files.length; i++) {
 FileObject currentFile = files[i];
 String currentFileBaseName = currentFile.getName().getBaseName();

 if (currentFile.getType().equals(FileType.FOLDER)) {
 addDir(currentFile, zout, basePathSoFar + currentFileBaseName + "/");

 } else { // else it's a file, not a directory
 BufferedInputStream bis = new
BufferedInputStream(currentFile.getContent().getInputStream());
 zout.putNextEntry(new ZipEntry(basePathSoFar + currentFileBaseName));
 int len;
 while ((len = bis.read(tmpBuf)) != -1) {
 zout.write(tmpBuf, 0, len);
 }
 zout.closeEntry();
 bis.close();
 } // end if
 } // end for loop
 } // end addDir
}


+ + + + + + + + + + + + + + + + + + + +





Happy New Year,
Stephen Huey




On Tue, Dec 15, 2009 at 1:54 AM, Stephen Huey <st...@gmail.com>wrote:

> I'm using GaeVFS which is based on Commons VFS, and I feel that my question
> is probably more relevant to Commons VFS than the Google App Engine layer on
> top of it.  My goal is to construct valid zip files on Google App Engine,
> and I successfully used GaeVFS to create zip files that Mac OS X can open
> and that Winzip on Windows can open, but Windows XP Compressed Folders
> refused to acknowledge files in subdirectories in the zip until I removed
> the leading forward slash from a ZipEntry whose name began with a
> directory.
>
> For example, the following basic class successfully generates a zip file
> containing a file in a subdirectory that Windows XP Compressed Folders will
> open:
>
>
> import java.util.zip.*;
> import java.io.*;
> public class ZipThis {
>   public static void main(String args[]) throws IOException {
>     if (args.length < 1) {
>       System.err.println("usage: java ZipThis Zip.zip");
>       System.exit(-1);
>     }
>     File zipFile = new File(args[0]);
>     if (zipFile.exists()) {
>       System.err.println("Zip file already exists, please try another");
>       System.exit(-2);
>     }
>     FileOutputStream fos = new FileOutputStream(zipFile);
>     ZipOutputStream zos = new ZipOutputStream(fos);
>     int bytesRead;
>     String[] files = new String[] {"D:/stylessub/styles.xml",
> "D:/document.xml"};
>     String[] entryName = new String[] {"stylessub/styles.xml",
> "document.xml"};
>     byte[] buffer = new byte[1024];
>     for (int i=0, n=files.length; i < n; i++) {
>       String name = files[i];
>       File file = new File(name);
>       if (!file.exists()) {
>         System.out.println("Skipping: " + name);
>         continue;
>       }
>       BufferedInputStream bis = new BufferedInputStream(new
> FileInputStream(file));
>       ZipEntry entry = new ZipEntry(entryName[i]);
>       zos.putNextEntry(entry);
>       while ((bytesRead = bis.read(buffer)) != -1) {
>         zos.write(buffer, 0, bytesRead);
>       }
>       bis.close();
>       zos.closeEntry();
>
>     }
>     zos.close();
>   }
> }
>
>
> Now I'm trying to get my virtual file system code to generate a zip that
> Windows won't complain about with this error message:  "The Compressed
> (zipped) Folder is isvalid or corrupted."  I want to meet the Microsoft
> employee who wrote that error message!  :)
>
> So here's some initial setup in my servlet:
>
> FileObject docxZipFile = FileObjectHelper.createFile(fsManager,
> "gae://gaevfs/generatedZip/docxFile.zip");
> FileObject docxRootFolder = FileObjectHelper.createFolder(fsManager,
> "gae://gaevfs/docxDirectory");
>
> These helper methods are being used:
>
>     public static FileObject createFile(FileSystemManager fsManager, String
> absolutePath) throws FileSystemException {
>         FileObject theFile = fsManager.resolveFile( absolutePath );
>         if ( theFile.exists() == false) {
>             theFile.createFile();
>         }
>         return theFile;
>     }
>
>     public static FileObject createFolder(FileSystemManager fsManager,
> String absolutePath) throws FileSystemException {
>         FileObject theFolder = fsManager.resolveFile( absolutePath );
>         if ( theFolder.exists() == false) {
>             theFolder.createFolder();
>         }
>         return theFolder;
>     }
>
> Pardon the near redundancy.  Anyway, the next line begins the zipping:
>
> FileObjectHelper.zipDir(docxZipFile, docxRootFolder);
>
>
> Here's the zipDir method:
>
>
>     public static void zipDir(FileObject docxZipFile, FileObject
> directoryToZip) throws Exception {
>         OutputStream out = docxZipFile.getContent().getOutputStream();
>         //ByteArrayOutputStream bos = new ByteArrayOutputStream();
>         ZipOutputStream zout = new ZipOutputStream(out);
>         addDir(directoryToZip, zout, directoryToZip.getName().getBaseName()
> + "/");
>         out.close();
>         //return bos.toByteArray();
>     }
>
>
> As you can see, I played with pushing down a byte array of the resulting
> zip file on the servlet output stream instead of saving the generated zip
> file to the virtual file system, but that didn't make my error message go
> away.  Here's the addDir method:
>
>
>     public static void addDir(FileObject dirObj, ZipOutputStream out,
> String basePathSoFar) throws IOException {
>         System.out.println("addDir for " + dirObj.getName());
>         FileObject[] files = dirObj.getChildren();
>         byte[] tmpBuf = new byte[1024];
>
>         for (int i = 0; i < files.length; i++) {
>             FileObject currentFile = files[i];
>             System.out.println("currentFile is " +
> currentFile.getName().getBaseName());
>             if (currentFile.getType().equals(FileType.FOLDER)) {
>                 addDir(currentFile, out, basePathSoFar +
> currentFile.getName().getBaseName() + "/");
>
>             } else {
>
>                 System.out.println("making entry for: " + basePathSoFar +
> currentFile.getName().getBaseName());
>                 InputStream in = currentFile.getContent().getInputStream();
>                 out.putNextEntry(new ZipEntry(basePathSoFar +
> currentFile.getName().getBaseName()));
>                 int len;
>                 while ((len = in.read(tmpBuf)) != -1) {
>                     out.write(tmpBuf, 0, len);
>                 }
>                 out.closeEntry();
>                 in.close();
>             }
>         } // end for loop
>     }
>
>
> I used to have the buffer read check for greater than zero rather than not
> equal to negative one.  Anyway, for some reason this doesn't work even
> though it seems very close to the working program above.  I'll paste the
> print statements down below so you can see that it doesn't appear as if VFS
> is putting any extra junk into the ZipEntry names or anything like that.
>
> I'd love to try out any bright ideas anyone has!
>
> Thanks so much...
>
>
>
> The server is running at http://localhost:8888/
> Passing the zip file:
> /D:/workspace/my-app/war/gaevfs/generatedZip/docxFile.zip
> Writing this zip file: docxFile.zip
> Zipping up  directory: docxDirectory
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory
> currentFile is _rels
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/_rels
> currentFile is docProps
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/docProps
> currentFile is app.xml
> making entry for: docxDirectory/docProps/app.xml
> currentFile is core.xml
> making entry for: docxDirectory/docProps/core.xml
> currentFile is word
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word
> currentFile is document.xml
> making entry for: docxDirectory/word/document.xml
> currentFile is fontTable.xml
> making entry for: docxDirectory/word/fontTable.xml
> currentFile is settings.xml
> making entry for: docxDirectory/word/settings.xml
> currentFile is styles.xml
> making entry for: docxDirectory/word/styles.xml
> currentFile is webSettings.xml
> making entry for: docxDirectory/word/webSettings.xml
> currentFile is _rels
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/_rels
> currentFile is document.xml.rels
> making entry for: docxDirectory/word/_rels/document.xml.rels
> currentFile is media
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/media
> currentFile is image1.jpeg
> making entry for: docxDirectory/word/media/image1.jpeg
> currentFile is image2.jpeg
> making entry for: docxDirectory/word/media/image2.jpeg
> currentFile is theme
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/theme
> currentFile is theme1.xml
> making entry for: docxDirectory/word/theme/theme1.xml
> currentFile is [Content_Types].xml
> making entry for: docxDirectory/[Content_Types].xml
> Passing the zip file:
> /D:/workspace/my-app/war/gaevfs/generatedZip/betterzip.zip
> Writing this zip file: betterzip.zip
> Zipping up  directory: docxDirectory
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory
> currentFile is _rels
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/_rels
> currentFile is docProps
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/docProps
> currentFile is app.xml
> making entry for: docxDirectory/docProps/app.xml
> currentFile is core.xml
> making entry for: docxDirectory/docProps/core.xml
> currentFile is word
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word
> currentFile is document.xml
> making entry for: docxDirectory/word/document.xml
> currentFile is fontTable.xml
> making entry for: docxDirectory/word/fontTable.xml
> currentFile is settings.xml
> making entry for: docxDirectory/word/settings.xml
> currentFile is styles.xml
> making entry for: docxDirectory/word/styles.xml
> currentFile is webSettings.xml
> making entry for: docxDirectory/word/webSettings.xml
> currentFile is _rels
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/_rels
> currentFile is document.xml.rels
> making entry for: docxDirectory/word/_rels/document.xml.rels
> currentFile is media
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/media
> currentFile is image1.jpeg
> making entry for: docxDirectory/word/media/image1.jpeg
> currentFile is image2.jpeg
> making entry for: docxDirectory/word/media/image2.jpeg
> currentFile is theme
> addDir for gae:///D:/workspace/my-app/war/gaevfs/docxDirectory/word/theme
> currentFile is theme1.xml
> making entry for: docxDirectory/word/theme/theme1.xml
> currentFile is [Content_Types].xml
> making entry for: docxDirectory/[Content_Types].xml
>
>

Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

Posted by Mark Fortner <ph...@gmail.com>.
Hi Stephen,
So if I understand your use case, you needed to be able to generate
Word and Excel reports. I had a similar requirement a while back and
used Microsoft's uncompressed  XML formats -- I simply saved the Word
and Excel files as  XML and inserted Velocity templating code in the
XML. I then made a servlet that handled the merging of data into the
template. It worked pretty well. The users would simply click on a
link and the report would then open up in either Word or Excel.  I
think the file format was supported in Word 2003, and since this was
an internal app we didn't have any concerns about supporting the older
file formats.

Hope this helps,

Mark

On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com> wrote:
> That might work with some source code modifications.  I remember digging
> through a bit of the Java example code here and realizing there were
> scattered references to the File class:
>
> http://openxmldeveloper.org/archive/category/1008.aspx
>
> GAE does not provide access to a file system, but GaeVFS would probably fix
> that issue with regard to the OpenXML4J code if I went into its source and
> edited references to that.  However, I'd imagine there would still be
> dependencies on unsupported libraries such as graphics for manipulating rich
> text even though the resulting files are just XML.  We don't have to change
> the design of our Word and Excel reports very much, so it's not too much
> work for us if we just manually create a template by typing up something
> pretty in each Microsoft Office application and then take that file and
> replace pieces of it with our dynamic data.  Yes, we're writing from scratch
> some code that POI already handles, but we already know our way works and
> the requirements are fairly minimal and static, so it doesn't seem
> worthwhile at this point to adapt POI to Google App Engine.
>
> That doesn't mean I don't wish it worked on there!  I'd be interested in
> hearing that it actually wouldn't be too difficult since all those classes
> are already written...
>
> Thanks,
> Stephen
>
>
>
> On Tue, Jan 5, 2010 at 8:05 PM, Mark Fortner <ph...@gmail.com> wrote:
>
>> Hi Stephen,
>> Here's a link to the POI Components page.
>> http://poi.apache.org/overview.html#components
>> If I remember correctly you need to add the poi-ooxml maven artifact to
>> your
>> build.
>>
>> There are some examples Here :
>> http://poi.apache.org/spreadsheet/examples.html
>>
>> I'm not sure that this fixes the problem that GAE has with the AWT API.
>>  The
>> main complaint in the bug report had to do with the usage of the Color
>> class, which may be used in a number of places to get or set the cell
>> color.
>>
>> The API was donated to the POI project, but started out as the OpenXML4j
>> project on sourceforge. https://sourceforge.net/projects/openxml4j/
>>
>> That version may not have any POI dependencies and may suit your needs
>> better.
>>
>> Mark
>>
>>
>> On Tue, Jan 5, 2010 at 4:28 PM, Stephen Huey <st...@gmail.com>
>> wrote:
>>
>> > Apache POI is currently labeled as Incompatible on Google App Engine:
>> >
>> >
>> >
>> http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine
>> >
>> > This post explains that awt references and maybe other similar issues are
>> > the problem:
>> > https://issues.apache.org/bugzilla/show_bug.cgi?id=47497
>> >
>> > I'm not familiar with the separate module for xlsx and docx, so perhaps
>> it
>> > would run on GAE if it can be used independently of the modules that use
>> > libraries not currently supported on GAE.  I'd be interested in knowing
>> if
>> > that's the case!
>> >
>> > Thanks so much,
>> > Stephen
>> >
>> >
>> >
>> > On Tue, Jan 5, 2010 at 6:00 PM, Mark Fortner <ph...@gmail.com>
>> wrote:
>> >
>> > > Hi Stephen,
>> > >
>> > > Thanks for posting this. I read your blog entry as well. You mention
>> > > in passing that POI doesn't support the new formats. There's a
>> > > separate module that is supposed to support xlsx and docx formats. I
>> > > was able to use them in the past. Was there some particular "gotcha"
>> > > that people should keep an eye out for?
>> > >
>> > > Regards,
>> > >
>> > > Mark
>> > >
>> > > On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com>
>> > wrote:
>> > > > For posterity's sake, I meant to come back here and post the solution
>> a
>> > > > while ago.  I've got the full story here in this blog post:
>> > > >
>> > > > http://stephenhuey.wordpress.com/2010/01/01/docxgae/
>> > > >
>> > > > The relatively new Microsoft Office formats ending with extensions
>> such
>> > > as
>> > > > .docx and .xlsx are zip files of directories of text files (XML) and
>> > > images.
>> > > >  Tried-and-true Java libraries for writing the old binary Microsoft
>> > Word
>> > > and
>> > > > Excel formats aren't yet supported on Google App Engine, so I was
>> glad
>> > to
>> > > > get this working since it was a required feature for our application.
>> > > >
>> > > > My modified code for the zipDir and addDir methods is below.  As you
>> > can
>> > > > see, I'm closing the ZipOutputStream rather than the OutputStream:
>> > > >
>> > > >
>> > > > + + + + +

-- 
Mark Fortner

blog: http://feeds.feedburner.com/jroller/ideafactory

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

Posted by Stephen Huey <st...@gmail.com>.
That might work with some source code modifications.  I remember digging
through a bit of the Java example code here and realizing there were
scattered references to the File class:

http://openxmldeveloper.org/archive/category/1008.aspx

GAE does not provide access to a file system, but GaeVFS would probably fix
that issue with regard to the OpenXML4J code if I went into its source and
edited references to that.  However, I'd imagine there would still be
dependencies on unsupported libraries such as graphics for manipulating rich
text even though the resulting files are just XML.  We don't have to change
the design of our Word and Excel reports very much, so it's not too much
work for us if we just manually create a template by typing up something
pretty in each Microsoft Office application and then take that file and
replace pieces of it with our dynamic data.  Yes, we're writing from scratch
some code that POI already handles, but we already know our way works and
the requirements are fairly minimal and static, so it doesn't seem
worthwhile at this point to adapt POI to Google App Engine.

That doesn't mean I don't wish it worked on there!  I'd be interested in
hearing that it actually wouldn't be too difficult since all those classes
are already written...

Thanks,
Stephen



On Tue, Jan 5, 2010 at 8:05 PM, Mark Fortner <ph...@gmail.com> wrote:

> Hi Stephen,
> Here's a link to the POI Components page.
> http://poi.apache.org/overview.html#components
> If I remember correctly you need to add the poi-ooxml maven artifact to
> your
> build.
>
> There are some examples Here :
> http://poi.apache.org/spreadsheet/examples.html
>
> I'm not sure that this fixes the problem that GAE has with the AWT API.
>  The
> main complaint in the bug report had to do with the usage of the Color
> class, which may be used in a number of places to get or set the cell
> color.
>
> The API was donated to the POI project, but started out as the OpenXML4j
> project on sourceforge. https://sourceforge.net/projects/openxml4j/
>
> That version may not have any POI dependencies and may suit your needs
> better.
>
> Mark
>
>
> On Tue, Jan 5, 2010 at 4:28 PM, Stephen Huey <st...@gmail.com>
> wrote:
>
> > Apache POI is currently labeled as Incompatible on Google App Engine:
> >
> >
> >
> http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine
> >
> > This post explains that awt references and maybe other similar issues are
> > the problem:
> > https://issues.apache.org/bugzilla/show_bug.cgi?id=47497
> >
> > I'm not familiar with the separate module for xlsx and docx, so perhaps
> it
> > would run on GAE if it can be used independently of the modules that use
> > libraries not currently supported on GAE.  I'd be interested in knowing
> if
> > that's the case!
> >
> > Thanks so much,
> > Stephen
> >
> >
> >
> > On Tue, Jan 5, 2010 at 6:00 PM, Mark Fortner <ph...@gmail.com>
> wrote:
> >
> > > Hi Stephen,
> > >
> > > Thanks for posting this. I read your blog entry as well. You mention
> > > in passing that POI doesn't support the new formats. There's a
> > > separate module that is supposed to support xlsx and docx formats. I
> > > was able to use them in the past. Was there some particular "gotcha"
> > > that people should keep an eye out for?
> > >
> > > Regards,
> > >
> > > Mark
> > >
> > > On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com>
> > wrote:
> > > > For posterity's sake, I meant to come back here and post the solution
> a
> > > > while ago.  I've got the full story here in this blog post:
> > > >
> > > > http://stephenhuey.wordpress.com/2010/01/01/docxgae/
> > > >
> > > > The relatively new Microsoft Office formats ending with extensions
> such
> > > as
> > > > .docx and .xlsx are zip files of directories of text files (XML) and
> > > images.
> > > >  Tried-and-true Java libraries for writing the old binary Microsoft
> > Word
> > > and
> > > > Excel formats aren't yet supported on Google App Engine, so I was
> glad
> > to
> > > > get this working since it was a required feature for our application.
> > > >
> > > > My modified code for the zipDir and addDir methods is below.  As you
> > can
> > > > see, I'm closing the ZipOutputStream rather than the OutputStream:
> > > >
> > > >
> > > > + + + + + + + + + + + + + + + + + + + +
> > > >
> > > >
> > > > import java.io.BufferedInputStream;
> > > > import java.io.IOException;
> > > > import java.io.OutputStream;
> > > > import java.util.zip.ZipEntry;
> > > > import java.util.zip.ZipOutputStream;
> > > >
> > > > import org.apache.commons.vfs.FileObject;
> > > > import org.apache.commons.vfs.FileSystemException;
> > > > import org.apache.commons.vfs.FileSystemManager;
> > > > import org.apache.commons.vfs.FileType;
> > > >
> > > > public class FileObjectHelper {
> > > >
> > > >  public static FileObject createFolder(FileSystemManager fsManager,
> > > String
> > > > absolutePath) throws FileSystemException {
> > > >  FileObject theFolder = fsManager.resolveFile( absolutePath );
> > > >  if ( theFolder.exists() == false) {
> > > >  theFolder.createFolder();
> > > >  }
> > > >  return theFolder;
> > > >  }
> > > >
> > > >  public static FileObject createFile(FileSystemManager fsManager,
> > String
> > > > absolutePath) throws FileSystemException {
> > > >  FileObject theFile = fsManager.resolveFile( absolutePath );
> > > >  if ( theFile.exists() == false) {
> > > >  theFile.createFile();
> > > >  }
> > > >  return theFile;
> > > >  }
> > > >
> > > >  public static void zipDir(FileObject docxZipFile, FileObject
> > > > directoryToZip) throws IOException {
> > > >  OutputStream out = docxZipFile.getContent().getOutputStream();
> > > >  ZipOutputStream zout = new ZipOutputStream(out);
> > > >  addDir(directoryToZip, zout, "");
> > > >  zout.close(); // make sure you close the ZipOutputStream, not the
> > > > OutputStream!
> > > >  }
> > > >
> > > >  public static void addDir(FileObject dirObj, ZipOutputStream zout,
> > > String
> > > > basePathSoFar) throws IOException {
> > > >  FileObject[] files = dirObj.getChildren();
> > > >  byte[] tmpBuf = new byte[1024];
> > > >
> > > >  for (int i = 0; i < files.length; i++) {
> > > >  FileObject currentFile = files[i];
> > > >  String currentFileBaseName = currentFile.getName().getBaseName();
> > > >
> > > >  if (currentFile.getType().equals(FileType.FOLDER)) {
> > > >  addDir(currentFile, zout, basePathSoFar + currentFileBaseName +
> "/");
> > > >
> > > >  } else { // else it's a file, not a directory
> > > >  BufferedInputStream bis = new
> > > > BufferedInputStream(currentFile.getContent().getInputStream());
> > > >  zout.putNextEntry(new ZipEntry(basePathSoFar +
> currentFileBaseName));
> > > >  int len;
> > > >  while ((len = bis.read(tmpBuf)) != -1) {
> > > >  zout.write(tmpBuf, 0, len);
> > > >  }
> > > >  zout.closeEntry();
> > > >  bis.close();
> > > >  } // end if
> > > >  } // end for loop
> > > >  } // end addDir
> > > > }
> > > >
> > > >
> > > > + + + + + + + + + + + + + + + + + + + +
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > Happy New Year,
> > > > Stephen Huey
> > > >
> > > >
> > > >
> > > >
> > > > On Tue, Dec 15, 2009 at 1:54 AM, Stephen Huey <
> stephen.huey@gmail.com
> > > >wrote:
> > > >
> > > >> I'm using GaeVFS which is based on Commons VFS, and I feel that my
> > > question
> > > >> is probably more relevant to Commons VFS than the Google App Engine
> > > layer on
> > > >> top of it.  My goal is to construct valid zip files on Google App
> > > Engine,
> > > >> and I successfully used GaeVFS to create zip files that Mac OS X can
> > > open
> > > >> and that Winzip on Windows can open, but Windows XP Compressed
> Folders
> > > >> refused to acknowledge files in subdirectories in the zip until I
> > > removed
> > > >> the leading forward slash from a ZipEntry whose name began with a
> > > >> directory.
> > > >>
> > > >> For example, the following basic class successfully generates a zip
> > file
> > > >> containing a file in a subdirectory that Windows XP Compressed
> Folders
> > > will
> > > >> open:
> > > >>
> > > >>
> > > >> import java.util.zip.*;
> > > >> import java.io.*;
> > > >> public class ZipThis {
> > > >>   public static void main(String args[]) throws IOException {
> > > >>     if (args.length < 1) {
> > > >>       System.err.println("usage: java ZipThis Zip.zip");
> > > >>       System.exit(-1);
> > > >>     }
> > > >>     File zipFile = new File(args[0]);
> > > >>     if (zipFile.exists()) {
> > > >>       System.err.println("Zip file already exists, please try
> > another");
> > > >>       System.exit(-2);
> > > >>     }
> > > >>     FileOutputStream fos = new FileOutputStream(zipFile);
> > > >>     ZipOutputStream zos = new ZipOutputStream(fos);
> > > >>     int bytesRead;
> > > >>     String[] files = new String[] {"D:/stylessub/styles.xml",
> > > >> "D:/document.xml"};
> > > >>     String[] entryName = new String[] {"stylessub/styles.xml",
> > > >> "document.xml"};
> > > >>     byte[] buffer = new byte[1024];
> > > >>     for (int i=0, n=files.length; i < n; i++) {
> > > >>       String name = files[i];
> > > >>       File file = new File(name);
> > > >>       if (!file.exists()) {
> > > >>         System.out.println("Skipping: " + name);
> > > >>         continue;
> > > >>       }
> > > >>       BufferedInputStream bis = new BufferedInputStream(new
> > > >> FileInputStream(file));
> > > >>       ZipEntry entry = new ZipEntry(entryName[i]);
> > > >>       zos.putNextEntry(entry);
> > > >>       while ((bytesRead = bis.read(buffer)) != -1) {
> > > >>         zos.write(buffer, 0, bytesRead);
> > > >>       }
> > > >>       bis.close();
> > > >>       zos.closeEntry();
> > > >>
> > > >>     }
> > > >>     zos.close();
> > > >>   }
> > > >> }
> > > >>
> > > >>
> > > >> Now I'm trying to get my virtual file system code to generate a zip
> > that
> > > >> Windows won't complain about with this error message:  "The
> Compressed
> > > >> (zipped) Folder is isvalid or corrupted."  I want to meet the
> > Microsoft
> > > >> employee who wrote that error message!  :)
> > > >>
> > > >> So here's some initial setup in my servlet:
> > > >>
> > > >> FileObject docxZipFile = FileObjectHelper.createFile(fsManager,
> > > >> "gae://gaevfs/generatedZip/docxFile.zip");
> > > >> FileObject docxRootFolder = FileObjectHelper.createFolder(fsManager,
> > > >> "gae://gaevfs/docxDirectory");
> > > >>
> > > >> These helper methods are being used:
> > > >>
> > > >>     public static FileObject createFile(FileSystemManager fsManager,
> > > String
> > > >> absolutePath) throws FileSystemException {
> > > >>         FileObject theFile = fsManager.resolveFile( absolutePath );
> > > >>         if ( theFile.exists() == false) {
> > > >>             theFile.createFile();
> > > >>         }
> > > >>         return theFile;
> > > >>     }
> > > >>
> > > >>     public static FileObject createFolder(FileSystemManager
> fsManager,
> > > >> String absolutePath) throws FileSystemException {
> > > >>         FileObject theFolder = fsManager.resolveFile( absolutePath
> );
> > > >>         if ( theFolder.exists() == false) {
> > > >>             theFolder.createFolder();
> > > >>         }
> > > >>         return theFolder;
> > > >>     }
> > > >>
> > > >> Pardon the near redundancy.  Anyway, the next line begins the
> zipping:
> > > >>
> > > >> FileObjectHelper.zipDir(docxZipFile, d
> > >
> > > --
> > > Mark Fortner
> > >
> > > blog: http://feeds.feedburner.com/jroller/ideafactory
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
> > > For additional commands, e-mail: user-help@commons.apache.org
> > >
> > >
> >
>
>
>
> --
> Mark Fortner
>
> blog: http://feeds.feedburner.com/jroller/ideafactory
>

Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

Posted by Mark Fortner <ph...@gmail.com>.
Hi Stephen,
Here's a link to the POI Components page.
http://poi.apache.org/overview.html#components
If I remember correctly you need to add the poi-ooxml maven artifact to your
build.

There are some examples Here :
http://poi.apache.org/spreadsheet/examples.html

I'm not sure that this fixes the problem that GAE has with the AWT API.  The
main complaint in the bug report had to do with the usage of the Color
class, which may be used in a number of places to get or set the cell color.

The API was donated to the POI project, but started out as the OpenXML4j
project on sourceforge. https://sourceforge.net/projects/openxml4j/

That version may not have any POI dependencies and may suit your needs
better.

Mark


On Tue, Jan 5, 2010 at 4:28 PM, Stephen Huey <st...@gmail.com> wrote:

> Apache POI is currently labeled as Incompatible on Google App Engine:
>
>
> http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine
>
> This post explains that awt references and maybe other similar issues are
> the problem:
> https://issues.apache.org/bugzilla/show_bug.cgi?id=47497
>
> I'm not familiar with the separate module for xlsx and docx, so perhaps it
> would run on GAE if it can be used independently of the modules that use
> libraries not currently supported on GAE.  I'd be interested in knowing if
> that's the case!
>
> Thanks so much,
> Stephen
>
>
>
> On Tue, Jan 5, 2010 at 6:00 PM, Mark Fortner <ph...@gmail.com> wrote:
>
> > Hi Stephen,
> >
> > Thanks for posting this. I read your blog entry as well. You mention
> > in passing that POI doesn't support the new formats. There's a
> > separate module that is supposed to support xlsx and docx formats. I
> > was able to use them in the past. Was there some particular "gotcha"
> > that people should keep an eye out for?
> >
> > Regards,
> >
> > Mark
> >
> > On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com>
> wrote:
> > > For posterity's sake, I meant to come back here and post the solution a
> > > while ago.  I've got the full story here in this blog post:
> > >
> > > http://stephenhuey.wordpress.com/2010/01/01/docxgae/
> > >
> > > The relatively new Microsoft Office formats ending with extensions such
> > as
> > > .docx and .xlsx are zip files of directories of text files (XML) and
> > images.
> > >  Tried-and-true Java libraries for writing the old binary Microsoft
> Word
> > and
> > > Excel formats aren't yet supported on Google App Engine, so I was glad
> to
> > > get this working since it was a required feature for our application.
> > >
> > > My modified code for the zipDir and addDir methods is below.  As you
> can
> > > see, I'm closing the ZipOutputStream rather than the OutputStream:
> > >
> > >
> > > + + + + + + + + + + + + + + + + + + + +
> > >
> > >
> > > import java.io.BufferedInputStream;
> > > import java.io.IOException;
> > > import java.io.OutputStream;
> > > import java.util.zip.ZipEntry;
> > > import java.util.zip.ZipOutputStream;
> > >
> > > import org.apache.commons.vfs.FileObject;
> > > import org.apache.commons.vfs.FileSystemException;
> > > import org.apache.commons.vfs.FileSystemManager;
> > > import org.apache.commons.vfs.FileType;
> > >
> > > public class FileObjectHelper {
> > >
> > >  public static FileObject createFolder(FileSystemManager fsManager,
> > String
> > > absolutePath) throws FileSystemException {
> > >  FileObject theFolder = fsManager.resolveFile( absolutePath );
> > >  if ( theFolder.exists() == false) {
> > >  theFolder.createFolder();
> > >  }
> > >  return theFolder;
> > >  }
> > >
> > >  public static FileObject createFile(FileSystemManager fsManager,
> String
> > > absolutePath) throws FileSystemException {
> > >  FileObject theFile = fsManager.resolveFile( absolutePath );
> > >  if ( theFile.exists() == false) {
> > >  theFile.createFile();
> > >  }
> > >  return theFile;
> > >  }
> > >
> > >  public static void zipDir(FileObject docxZipFile, FileObject
> > > directoryToZip) throws IOException {
> > >  OutputStream out = docxZipFile.getContent().getOutputStream();
> > >  ZipOutputStream zout = new ZipOutputStream(out);
> > >  addDir(directoryToZip, zout, "");
> > >  zout.close(); // make sure you close the ZipOutputStream, not the
> > > OutputStream!
> > >  }
> > >
> > >  public static void addDir(FileObject dirObj, ZipOutputStream zout,
> > String
> > > basePathSoFar) throws IOException {
> > >  FileObject[] files = dirObj.getChildren();
> > >  byte[] tmpBuf = new byte[1024];
> > >
> > >  for (int i = 0; i < files.length; i++) {
> > >  FileObject currentFile = files[i];
> > >  String currentFileBaseName = currentFile.getName().getBaseName();
> > >
> > >  if (currentFile.getType().equals(FileType.FOLDER)) {
> > >  addDir(currentFile, zout, basePathSoFar + currentFileBaseName + "/");
> > >
> > >  } else { // else it's a file, not a directory
> > >  BufferedInputStream bis = new
> > > BufferedInputStream(currentFile.getContent().getInputStream());
> > >  zout.putNextEntry(new ZipEntry(basePathSoFar + currentFileBaseName));
> > >  int len;
> > >  while ((len = bis.read(tmpBuf)) != -1) {
> > >  zout.write(tmpBuf, 0, len);
> > >  }
> > >  zout.closeEntry();
> > >  bis.close();
> > >  } // end if
> > >  } // end for loop
> > >  } // end addDir
> > > }
> > >
> > >
> > > + + + + + + + + + + + + + + + + + + + +
> > >
> > >
> > >
> > >
> > >
> > > Happy New Year,
> > > Stephen Huey
> > >
> > >
> > >
> > >
> > > On Tue, Dec 15, 2009 at 1:54 AM, Stephen Huey <stephen.huey@gmail.com
> > >wrote:
> > >
> > >> I'm using GaeVFS which is based on Commons VFS, and I feel that my
> > question
> > >> is probably more relevant to Commons VFS than the Google App Engine
> > layer on
> > >> top of it.  My goal is to construct valid zip files on Google App
> > Engine,
> > >> and I successfully used GaeVFS to create zip files that Mac OS X can
> > open
> > >> and that Winzip on Windows can open, but Windows XP Compressed Folders
> > >> refused to acknowledge files in subdirectories in the zip until I
> > removed
> > >> the leading forward slash from a ZipEntry whose name began with a
> > >> directory.
> > >>
> > >> For example, the following basic class successfully generates a zip
> file
> > >> containing a file in a subdirectory that Windows XP Compressed Folders
> > will
> > >> open:
> > >>
> > >>
> > >> import java.util.zip.*;
> > >> import java.io.*;
> > >> public class ZipThis {
> > >>   public static void main(String args[]) throws IOException {
> > >>     if (args.length < 1) {
> > >>       System.err.println("usage: java ZipThis Zip.zip");
> > >>       System.exit(-1);
> > >>     }
> > >>     File zipFile = new File(args[0]);
> > >>     if (zipFile.exists()) {
> > >>       System.err.println("Zip file already exists, please try
> another");
> > >>       System.exit(-2);
> > >>     }
> > >>     FileOutputStream fos = new FileOutputStream(zipFile);
> > >>     ZipOutputStream zos = new ZipOutputStream(fos);
> > >>     int bytesRead;
> > >>     String[] files = new String[] {"D:/stylessub/styles.xml",
> > >> "D:/document.xml"};
> > >>     String[] entryName = new String[] {"stylessub/styles.xml",
> > >> "document.xml"};
> > >>     byte[] buffer = new byte[1024];
> > >>     for (int i=0, n=files.length; i < n; i++) {
> > >>       String name = files[i];
> > >>       File file = new File(name);
> > >>       if (!file.exists()) {
> > >>         System.out.println("Skipping: " + name);
> > >>         continue;
> > >>       }
> > >>       BufferedInputStream bis = new BufferedInputStream(new
> > >> FileInputStream(file));
> > >>       ZipEntry entry = new ZipEntry(entryName[i]);
> > >>       zos.putNextEntry(entry);
> > >>       while ((bytesRead = bis.read(buffer)) != -1) {
> > >>         zos.write(buffer, 0, bytesRead);
> > >>       }
> > >>       bis.close();
> > >>       zos.closeEntry();
> > >>
> > >>     }
> > >>     zos.close();
> > >>   }
> > >> }
> > >>
> > >>
> > >> Now I'm trying to get my virtual file system code to generate a zip
> that
> > >> Windows won't complain about with this error message:  "The Compressed
> > >> (zipped) Folder is isvalid or corrupted."  I want to meet the
> Microsoft
> > >> employee who wrote that error message!  :)
> > >>
> > >> So here's some initial setup in my servlet:
> > >>
> > >> FileObject docxZipFile = FileObjectHelper.createFile(fsManager,
> > >> "gae://gaevfs/generatedZip/docxFile.zip");
> > >> FileObject docxRootFolder = FileObjectHelper.createFolder(fsManager,
> > >> "gae://gaevfs/docxDirectory");
> > >>
> > >> These helper methods are being used:
> > >>
> > >>     public static FileObject createFile(FileSystemManager fsManager,
> > String
> > >> absolutePath) throws FileSystemException {
> > >>         FileObject theFile = fsManager.resolveFile( absolutePath );
> > >>         if ( theFile.exists() == false) {
> > >>             theFile.createFile();
> > >>         }
> > >>         return theFile;
> > >>     }
> > >>
> > >>     public static FileObject createFolder(FileSystemManager fsManager,
> > >> String absolutePath) throws FileSystemException {
> > >>         FileObject theFolder = fsManager.resolveFile( absolutePath );
> > >>         if ( theFolder.exists() == false) {
> > >>             theFolder.createFolder();
> > >>         }
> > >>         return theFolder;
> > >>     }
> > >>
> > >> Pardon the near redundancy.  Anyway, the next line begins the zipping:
> > >>
> > >> FileObjectHelper.zipDir(docxZipFile, d
> >
> > --
> > Mark Fortner
> >
> > blog: http://feeds.feedburner.com/jroller/ideafactory
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
> > For additional commands, e-mail: user-help@commons.apache.org
> >
> >
>



-- 
Mark Fortner

blog: http://feeds.feedburner.com/jroller/ideafactory

Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

Posted by Stephen Huey <st...@gmail.com>.
Apache POI is currently labeled as Incompatible on Google App Engine:

http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine

This post explains that awt references and maybe other similar issues are
the problem:
https://issues.apache.org/bugzilla/show_bug.cgi?id=47497

I'm not familiar with the separate module for xlsx and docx, so perhaps it
would run on GAE if it can be used independently of the modules that use
libraries not currently supported on GAE.  I'd be interested in knowing if
that's the case!

Thanks so much,
Stephen



On Tue, Jan 5, 2010 at 6:00 PM, Mark Fortner <ph...@gmail.com> wrote:

> Hi Stephen,
>
> Thanks for posting this. I read your blog entry as well. You mention
> in passing that POI doesn't support the new formats. There's a
> separate module that is supposed to support xlsx and docx formats. I
> was able to use them in the past. Was there some particular "gotcha"
> that people should keep an eye out for?
>
> Regards,
>
> Mark
>
> On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com> wrote:
> > For posterity's sake, I meant to come back here and post the solution a
> > while ago.  I've got the full story here in this blog post:
> >
> > http://stephenhuey.wordpress.com/2010/01/01/docxgae/
> >
> > The relatively new Microsoft Office formats ending with extensions such
> as
> > .docx and .xlsx are zip files of directories of text files (XML) and
> images.
> >  Tried-and-true Java libraries for writing the old binary Microsoft Word
> and
> > Excel formats aren't yet supported on Google App Engine, so I was glad to
> > get this working since it was a required feature for our application.
> >
> > My modified code for the zipDir and addDir methods is below.  As you can
> > see, I'm closing the ZipOutputStream rather than the OutputStream:
> >
> >
> > + + + + + + + + + + + + + + + + + + + +
> >
> >
> > import java.io.BufferedInputStream;
> > import java.io.IOException;
> > import java.io.OutputStream;
> > import java.util.zip.ZipEntry;
> > import java.util.zip.ZipOutputStream;
> >
> > import org.apache.commons.vfs.FileObject;
> > import org.apache.commons.vfs.FileSystemException;
> > import org.apache.commons.vfs.FileSystemManager;
> > import org.apache.commons.vfs.FileType;
> >
> > public class FileObjectHelper {
> >
> >  public static FileObject createFolder(FileSystemManager fsManager,
> String
> > absolutePath) throws FileSystemException {
> >  FileObject theFolder = fsManager.resolveFile( absolutePath );
> >  if ( theFolder.exists() == false) {
> >  theFolder.createFolder();
> >  }
> >  return theFolder;
> >  }
> >
> >  public static FileObject createFile(FileSystemManager fsManager, String
> > absolutePath) throws FileSystemException {
> >  FileObject theFile = fsManager.resolveFile( absolutePath );
> >  if ( theFile.exists() == false) {
> >  theFile.createFile();
> >  }
> >  return theFile;
> >  }
> >
> >  public static void zipDir(FileObject docxZipFile, FileObject
> > directoryToZip) throws IOException {
> >  OutputStream out = docxZipFile.getContent().getOutputStream();
> >  ZipOutputStream zout = new ZipOutputStream(out);
> >  addDir(directoryToZip, zout, "");
> >  zout.close(); // make sure you close the ZipOutputStream, not the
> > OutputStream!
> >  }
> >
> >  public static void addDir(FileObject dirObj, ZipOutputStream zout,
> String
> > basePathSoFar) throws IOException {
> >  FileObject[] files = dirObj.getChildren();
> >  byte[] tmpBuf = new byte[1024];
> >
> >  for (int i = 0; i < files.length; i++) {
> >  FileObject currentFile = files[i];
> >  String currentFileBaseName = currentFile.getName().getBaseName();
> >
> >  if (currentFile.getType().equals(FileType.FOLDER)) {
> >  addDir(currentFile, zout, basePathSoFar + currentFileBaseName + "/");
> >
> >  } else { // else it's a file, not a directory
> >  BufferedInputStream bis = new
> > BufferedInputStream(currentFile.getContent().getInputStream());
> >  zout.putNextEntry(new ZipEntry(basePathSoFar + currentFileBaseName));
> >  int len;
> >  while ((len = bis.read(tmpBuf)) != -1) {
> >  zout.write(tmpBuf, 0, len);
> >  }
> >  zout.closeEntry();
> >  bis.close();
> >  } // end if
> >  } // end for loop
> >  } // end addDir
> > }
> >
> >
> > + + + + + + + + + + + + + + + + + + + +
> >
> >
> >
> >
> >
> > Happy New Year,
> > Stephen Huey
> >
> >
> >
> >
> > On Tue, Dec 15, 2009 at 1:54 AM, Stephen Huey <stephen.huey@gmail.com
> >wrote:
> >
> >> I'm using GaeVFS which is based on Commons VFS, and I feel that my
> question
> >> is probably more relevant to Commons VFS than the Google App Engine
> layer on
> >> top of it.  My goal is to construct valid zip files on Google App
> Engine,
> >> and I successfully used GaeVFS to create zip files that Mac OS X can
> open
> >> and that Winzip on Windows can open, but Windows XP Compressed Folders
> >> refused to acknowledge files in subdirectories in the zip until I
> removed
> >> the leading forward slash from a ZipEntry whose name began with a
> >> directory.
> >>
> >> For example, the following basic class successfully generates a zip file
> >> containing a file in a subdirectory that Windows XP Compressed Folders
> will
> >> open:
> >>
> >>
> >> import java.util.zip.*;
> >> import java.io.*;
> >> public class ZipThis {
> >>   public static void main(String args[]) throws IOException {
> >>     if (args.length < 1) {
> >>       System.err.println("usage: java ZipThis Zip.zip");
> >>       System.exit(-1);
> >>     }
> >>     File zipFile = new File(args[0]);
> >>     if (zipFile.exists()) {
> >>       System.err.println("Zip file already exists, please try another");
> >>       System.exit(-2);
> >>     }
> >>     FileOutputStream fos = new FileOutputStream(zipFile);
> >>     ZipOutputStream zos = new ZipOutputStream(fos);
> >>     int bytesRead;
> >>     String[] files = new String[] {"D:/stylessub/styles.xml",
> >> "D:/document.xml"};
> >>     String[] entryName = new String[] {"stylessub/styles.xml",
> >> "document.xml"};
> >>     byte[] buffer = new byte[1024];
> >>     for (int i=0, n=files.length; i < n; i++) {
> >>       String name = files[i];
> >>       File file = new File(name);
> >>       if (!file.exists()) {
> >>         System.out.println("Skipping: " + name);
> >>         continue;
> >>       }
> >>       BufferedInputStream bis = new BufferedInputStream(new
> >> FileInputStream(file));
> >>       ZipEntry entry = new ZipEntry(entryName[i]);
> >>       zos.putNextEntry(entry);
> >>       while ((bytesRead = bis.read(buffer)) != -1) {
> >>         zos.write(buffer, 0, bytesRead);
> >>       }
> >>       bis.close();
> >>       zos.closeEntry();
> >>
> >>     }
> >>     zos.close();
> >>   }
> >> }
> >>
> >>
> >> Now I'm trying to get my virtual file system code to generate a zip that
> >> Windows won't complain about with this error message:  "The Compressed
> >> (zipped) Folder is isvalid or corrupted."  I want to meet the Microsoft
> >> employee who wrote that error message!  :)
> >>
> >> So here's some initial setup in my servlet:
> >>
> >> FileObject docxZipFile = FileObjectHelper.createFile(fsManager,
> >> "gae://gaevfs/generatedZip/docxFile.zip");
> >> FileObject docxRootFolder = FileObjectHelper.createFolder(fsManager,
> >> "gae://gaevfs/docxDirectory");
> >>
> >> These helper methods are being used:
> >>
> >>     public static FileObject createFile(FileSystemManager fsManager,
> String
> >> absolutePath) throws FileSystemException {
> >>         FileObject theFile = fsManager.resolveFile( absolutePath );
> >>         if ( theFile.exists() == false) {
> >>             theFile.createFile();
> >>         }
> >>         return theFile;
> >>     }
> >>
> >>     public static FileObject createFolder(FileSystemManager fsManager,
> >> String absolutePath) throws FileSystemException {
> >>         FileObject theFolder = fsManager.resolveFile( absolutePath );
> >>         if ( theFolder.exists() == false) {
> >>             theFolder.createFolder();
> >>         }
> >>         return theFolder;
> >>     }
> >>
> >> Pardon the near redundancy.  Anyway, the next line begins the zipping:
> >>
> >> FileObjectHelper.zipDir(docxZipFile, d
>
> --
> Mark Fortner
>
> blog: http://feeds.feedburner.com/jroller/ideafactory
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
> For additional commands, e-mail: user-help@commons.apache.org
>
>

Re: Windows XP Compressed Folders doesn't recognize my VFS-based zip file

Posted by Mark Fortner <ph...@gmail.com>.
Hi Stephen,

Thanks for posting this. I read your blog entry as well. You mention
in passing that POI doesn't support the new formats. There's a
separate module that is supposed to support xlsx and docx formats. I
was able to use them in the past. Was there some particular "gotcha"
that people should keep an eye out for?

Regards,

Mark

On Tuesday, January 5, 2010, Stephen Huey <st...@gmail.com> wrote:
> For posterity's sake, I meant to come back here and post the solution a
> while ago.  I've got the full story here in this blog post:
>
> http://stephenhuey.wordpress.com/2010/01/01/docxgae/
>
> The relatively new Microsoft Office formats ending with extensions such as
> .docx and .xlsx are zip files of directories of text files (XML) and images.
>  Tried-and-true Java libraries for writing the old binary Microsoft Word and
> Excel formats aren't yet supported on Google App Engine, so I was glad to
> get this working since it was a required feature for our application.
>
> My modified code for the zipDir and addDir methods is below.  As you can
> see, I'm closing the ZipOutputStream rather than the OutputStream:
>
>
> + + + + + + + + + + + + + + + + + + + +
>
>
> import java.io.BufferedInputStream;
> import java.io.IOException;
> import java.io.OutputStream;
> import java.util.zip.ZipEntry;
> import java.util.zip.ZipOutputStream;
>
> import org.apache.commons.vfs.FileObject;
> import org.apache.commons.vfs.FileSystemException;
> import org.apache.commons.vfs.FileSystemManager;
> import org.apache.commons.vfs.FileType;
>
> public class FileObjectHelper {
>
>  public static FileObject createFolder(FileSystemManager fsManager, String
> absolutePath) throws FileSystemException {
>  FileObject theFolder = fsManager.resolveFile( absolutePath );
>  if ( theFolder.exists() == false) {
>  theFolder.createFolder();
>  }
>  return theFolder;
>  }
>
>  public static FileObject createFile(FileSystemManager fsManager, String
> absolutePath) throws FileSystemException {
>  FileObject theFile = fsManager.resolveFile( absolutePath );
>  if ( theFile.exists() == false) {
>  theFile.createFile();
>  }
>  return theFile;
>  }
>
>  public static void zipDir(FileObject docxZipFile, FileObject
> directoryToZip) throws IOException {
>  OutputStream out = docxZipFile.getContent().getOutputStream();
>  ZipOutputStream zout = new ZipOutputStream(out);
>  addDir(directoryToZip, zout, "");
>  zout.close(); // make sure you close the ZipOutputStream, not the
> OutputStream!
>  }
>
>  public static void addDir(FileObject dirObj, ZipOutputStream zout, String
> basePathSoFar) throws IOException {
>  FileObject[] files = dirObj.getChildren();
>  byte[] tmpBuf = new byte[1024];
>
>  for (int i = 0; i < files.length; i++) {
>  FileObject currentFile = files[i];
>  String currentFileBaseName = currentFile.getName().getBaseName();
>
>  if (currentFile.getType().equals(FileType.FOLDER)) {
>  addDir(currentFile, zout, basePathSoFar + currentFileBaseName + "/");
>
>  } else { // else it's a file, not a directory
>  BufferedInputStream bis = new
> BufferedInputStream(currentFile.getContent().getInputStream());
>  zout.putNextEntry(new ZipEntry(basePathSoFar + currentFileBaseName));
>  int len;
>  while ((len = bis.read(tmpBuf)) != -1) {
>  zout.write(tmpBuf, 0, len);
>  }
>  zout.closeEntry();
>  bis.close();
>  } // end if
>  } // end for loop
>  } // end addDir
> }
>
>
> + + + + + + + + + + + + + + + + + + + +
>
>
>
>
>
> Happy New Year,
> Stephen Huey
>
>
>
>
> On Tue, Dec 15, 2009 at 1:54 AM, Stephen Huey <st...@gmail.com>wrote:
>
>> I'm using GaeVFS which is based on Commons VFS, and I feel that my question
>> is probably more relevant to Commons VFS than the Google App Engine layer on
>> top of it.  My goal is to construct valid zip files on Google App Engine,
>> and I successfully used GaeVFS to create zip files that Mac OS X can open
>> and that Winzip on Windows can open, but Windows XP Compressed Folders
>> refused to acknowledge files in subdirectories in the zip until I removed
>> the leading forward slash from a ZipEntry whose name began with a
>> directory.
>>
>> For example, the following basic class successfully generates a zip file
>> containing a file in a subdirectory that Windows XP Compressed Folders will
>> open:
>>
>>
>> import java.util.zip.*;
>> import java.io.*;
>> public class ZipThis {
>>   public static void main(String args[]) throws IOException {
>>     if (args.length < 1) {
>>       System.err.println("usage: java ZipThis Zip.zip");
>>       System.exit(-1);
>>     }
>>     File zipFile = new File(args[0]);
>>     if (zipFile.exists()) {
>>       System.err.println("Zip file already exists, please try another");
>>       System.exit(-2);
>>     }
>>     FileOutputStream fos = new FileOutputStream(zipFile);
>>     ZipOutputStream zos = new ZipOutputStream(fos);
>>     int bytesRead;
>>     String[] files = new String[] {"D:/stylessub/styles.xml",
>> "D:/document.xml"};
>>     String[] entryName = new String[] {"stylessub/styles.xml",
>> "document.xml"};
>>     byte[] buffer = new byte[1024];
>>     for (int i=0, n=files.length; i < n; i++) {
>>       String name = files[i];
>>       File file = new File(name);
>>       if (!file.exists()) {
>>         System.out.println("Skipping: " + name);
>>         continue;
>>       }
>>       BufferedInputStream bis = new BufferedInputStream(new
>> FileInputStream(file));
>>       ZipEntry entry = new ZipEntry(entryName[i]);
>>       zos.putNextEntry(entry);
>>       while ((bytesRead = bis.read(buffer)) != -1) {
>>         zos.write(buffer, 0, bytesRead);
>>       }
>>       bis.close();
>>       zos.closeEntry();
>>
>>     }
>>     zos.close();
>>   }
>> }
>>
>>
>> Now I'm trying to get my virtual file system code to generate a zip that
>> Windows won't complain about with this error message:  "The Compressed
>> (zipped) Folder is isvalid or corrupted."  I want to meet the Microsoft
>> employee who wrote that error message!  :)
>>
>> So here's some initial setup in my servlet:
>>
>> FileObject docxZipFile = FileObjectHelper.createFile(fsManager,
>> "gae://gaevfs/generatedZip/docxFile.zip");
>> FileObject docxRootFolder = FileObjectHelper.createFolder(fsManager,
>> "gae://gaevfs/docxDirectory");
>>
>> These helper methods are being used:
>>
>>     public static FileObject createFile(FileSystemManager fsManager, String
>> absolutePath) throws FileSystemException {
>>         FileObject theFile = fsManager.resolveFile( absolutePath );
>>         if ( theFile.exists() == false) {
>>             theFile.createFile();
>>         }
>>         return theFile;
>>     }
>>
>>     public static FileObject createFolder(FileSystemManager fsManager,
>> String absolutePath) throws FileSystemException {
>>         FileObject theFolder = fsManager.resolveFile( absolutePath );
>>         if ( theFolder.exists() == false) {
>>             theFolder.createFolder();
>>         }
>>         return theFolder;
>>     }
>>
>> Pardon the near redundancy.  Anyway, the next line begins the zipping:
>>
>> FileObjectHelper.zipDir(docxZipFile, d

-- 
Mark Fortner

blog: http://feeds.feedburner.com/jroller/ideafactory

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org