Example of extracting a zip file in memory to CMIS using Java

76 views Asked by At

As already mentioned, I want to extract a zip file which I have as input stream to a repository (Alfresco) using CMIS and apache-commons.

I am using apache commons compress and opemcmis to achive this. The fowlloing code is working, but I would be happy if the community can help me, if I have overseen something and it this approach does not have any bugs. The code can be used by anyone who need it.

private static void unzip(CmisClient cmisClient, Folder target, ZipFile zip, ZipArchiveEntry entry) {
    String targetPath = target.getPath() + "/";
    if (entry.isDirectory()) {
        System.out.println("Folder...");
        CmisObject lastFoundObject = target;

        for(String name : entry.getName().split("/")) {

            String newPath = targetPath+name+"/";
            //
            // Try to finde the name
            //
            try {
                // Check if the path already exists
                System.out.println("Looking for path: "+newPath);
                CmisObject object = cmisClient.getSession().getObjectByPath(newPath);
                System.out.println("Folder already exists: " + newPath);

                lastFoundObject = object;
                targetPath = newPath;
            } catch (CmisObjectNotFoundException e) {
                System.out.println("Folder does not exists: " + entry.getName());
                // Create a new folder inside the last found CmisObject
                Folder folder = CmisUtil.createFolder(cmisClient, (Folder) lastFoundObject, name, "");
                System.out.println("Created folder: "+folder.getPath());
                // Set the created folder as the last found object
                lastFoundObject = folder;
                // Set the new target path
                targetPath = folder.getPath();
            }
        }
    } else {
        System.out.println("File...");
        String fullPath = entry.getName();
        String split[] = fullPath.split("/");
        if(split.length > 0) {
            String filename = split[split.length-1];
            String path = fullPath.replace(filename, "");

            if(filename.startsWith(".")) {
                System.out.println("Filename is ignored: "+filename);
            } else {
                System.out.println("Create file with path: "+entry.getName());
                System.out.println("Path: "+path);
                System.out.println("Filename: "+filename);

                try {
                    CmisObject folderObject = cmisClient.getSession().getObjectByPath(targetPath+path);

                    InputStream inputStream = zip.getInputStream(entry);
                    String mime = Files.probeContentType(new File(filename).toPath());

                    // Upload the file inside the CMIS object (FGolder)
                    CmisUtil.createDocument(cmisClient, (Folder) folderObject, filename, mime, IOUtils.toByteArray(inputStream));

                } catch(CmisObjectNotFoundException e) {
                    System.out.println("Parent folder not found, cannot unzip file: "+targetPath+path);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (DocumentAlreadyExistsInFolder e) {
                    throw new RuntimeException(e);
                }

            }
        } else {
            System.out.println("Split.length is null.");
        }
    }
}

This method makes more or less the complete task. It checks if the parh is a directory or a file, if it is a directory a CMIS directory is created, if it is a file a document is created. I ignore any file which starts with a point.

I use this method to start the extraction, because if there is more than one directory in the zip, this method calls the above method for each folder. I use the SeekableInMemoryByteChannel to convert the input stream:

public static void unzipToCmis(CmisClient cmisClient, Folder target, InputStream inputStream) throws IOException {
    //ZipArchiveInputStream zip = new ZipArchiveInputStream(inputStream);

    SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(IOUtils.toByteArray(inputStream));
    ZipFile zip = new ZipFile(inMemoryByteChannel);

    try {
        for (Iterator<ZipArchiveEntry> it = zip.getEntries().asIterator(); it.hasNext(); ) {
            ZipArchiveEntry entry = it.next();
            unzip(cmisClient, target, zip, entry);
        }
    } finally {
        zip.close();
    }
}

This is a simple main method to test it, I load a zip file from the local computer, convert it into an input stream and start the unzip process:

public static void main(String [] args) throws IOException {
    File initialFile = new File("/Users/florian/Downloads/Q3.zip");
    InputStream targetStream = new FileInputStream(initialFile);

    Organization organization = OrganizationUtil.getOrganization("pci");
    CmisClient client = new CmisClient();
    Folder parent = DmsUtil.getOrganizationFolder(client, organization);

    unzipToCmis(client, parent, targetStream);
}

Thic class should be used in a webapplication (some kind of document management system) where I can upload a zip file and can extract it to the repository. I use the cmsi approach to communicate with the repository because of it simple interface deign which is more than enough for my needs.

It would be very kind im someone can give me some feedback about this approach.

Thanks, Florian

0

There are 0 answers