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 <[email protected]> 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 <[email protected]>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: [email protected] For additional commands, e-mail: [email protected]
