Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Corrupted docx generated using zipping

Let me just start out by saying I created an account on here because I've been beating my head against a wall in order to try and figure this out, so here it goes.

Also, I have already seen this question here. Neither one of those answers have helped and I have tried both of them.

I need to create a word document with a simple table and data inside. I decided to create a sample document in which to get the xml that I need to create the document. I moved all the folders from the unzipped docx file into my assets folder. Once I realized I couldn't write to the assets folder, I wrote a method to copy all the files and folders over to an external storage location of the device and then write the document I created to the same location. From there Im trying to zip the files back up to a .docx file. This is where things arent working.

The actual docx file is created and I can move it to my computer through the DDMS but when I go to view it Word says its corrupt. Heres whats weird though, if I unzip it and then rezip it on my computer without making any changes what so ever it works perfectly. I have used a program (for mac) called DiffMerge to compare the sample unzipped docx file to the unzipped docx that I have created and it says they are exactly the same. So, I think it has something to do with the zipping process in Android.

I have also tried unzipping the sample docx file on my computer, moving all the files and folders over to my assets folder including the document.xml file and just try to zip it up without adding my own document.xml file and using the sample one and that doesnt work either. Another thing I tried was to place the actual docx file in my assets folder, unzipping it onto my external storage and then rezipping it without doing anything. This also fails.

I'm basically at a loss. Please somebody help me figure this out.

Here is some of my code:

  1. moveDocxFoldersFromAssetsToExternalStorage() is called first.
  2. After that is called all the files have been moved over.
  3. Then, I create the document.xml file and place it in the word directory where it belongs
  4. Everything is where it should be and I now try to create the zip file.

.

private boolean moveDocxFoldersFromAssetsToExternalStorage(){
    File rootDir = new File(this.externalPath);
    rootDir.mkdir();

    copy("");

    // This is to get around a glitch in Android which doesnt list files or folders
    // with an underscore at the beginning of the name in the assets folder.
    // This renames them once they are saved to the device.
    // We need it to show up in the list in order to move them.

    File relsDir = new File(this.externalPath + "/word/rels");
    File renameDir = new File(this.externalPath + "/word/_rels");
    relsDir.renameTo(renameDir);

    relsDir = new File(this.externalPath + "/rels");
    renameDir = new File(this.externalPath + "/_rels");
    relsDir.renameTo(renameDir);

    // This is to get around a glitch in Android which doesnt list hidden files.
    // We need it to show up in the list in order to move it.

    relsDir = new File(this.externalPath + "/_rels/rels.rename");
    renameDir = new File(this.externalPath + "/_rels/.rels");
    relsDir.renameTo(renameDir);

    return true;
}

private void copy(String outFileRelativePath){
    String files[] = null;
    try {
        files = this.mAssetManager.list(ASSETS_RELATIVE_PATH + outFileRelativePath);
    } catch (IOException e) {
        e.printStackTrace();
    }

    String assetFilePath = null;
    for(String fileName : files){
        if(!fileName.contains(".")){
            String outFile = outFileRelativePath + java.io.File.separator + fileName;
            copy(outFile);
        } else {
            File createFile = new File(this.externalPath + java.io.File.separator + outFileRelativePath);
            createFile.mkdir();
            File file = new File(createFile, fileName);

            assetFilePath = 
                ASSETS_RELATIVE_PATH + outFileRelativePath + java.io.File.separator + fileName;

            InputStream in = null;
            OutputStream out = null;
            try {
                in = this.mAssetManager.open(assetFilePath);
                out = new FileOutputStream(file);
                copyFile(in, out);
                in.close();
                out.flush();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

private void copyFile(InputStream in, OutputStream out) throws IOException {
    byte[] buffer = new byte[1024];
    int read;
    while((read = in.read(buffer)) != -1){
        out.write(buffer, 0, read);
    }
}

private void zipFolder(String srcFolder, String destZipFile) throws Exception{
    FileOutputStream fileWriter = new FileOutputStream(destZipFile);
    ZipOutputStream zip = new ZipOutputStream(fileWriter);
    zip.setMethod(Deflater.DEFLATED);
    zip.setLevel(ZipOutputStream.STORED);

    addFolderToZip(this.externalPath, "", zip);

    zip.finish();
    zip.close();
}


private void addFolderToZip(String externalPath, String folder, ZipOutputStream zip){
    File file = new File(externalPath);
    String files[] = file.list();

    for(String fileName : files){
        try {
            File currentFile = new File(externalPath, fileName);
            if(currentFile.isDirectory()){
                String outFile = externalPath + java.io.File.separator + fileName;          
                addFolderToZip(outFile, folder + java.io.File.separator + fileName, zip);
            } else {
                byte[] buffer = new byte[8000];
                int len;
                FileInputStream in = new FileInputStream(currentFile);
                zip.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
                while((len = in.read(buffer)) > 0){
                    zip.write(buffer, 0, len);
                }
                zip.closeEntry();
                in.close();
            }
        } catch (IOException e) {
                e.printStackTrace();
        }
    }
}

EDIT

Here is the code I wrote in order to get it working correctly based on what @edi9999 said below. I created a separate class that Im going to expand and add to and probably clean up a bit but this is working code. It adds all the files in a directory to the zip file and recursively calls itself to add all the subfiles and folders.

private class Zip {
    private ZipOutputStream mZipOutputStream;
    private String pathToZipDestination;
    private String pathToFilesToZip;

    public Zip(String pathToZipDestination, String pathToFilesToZip) {
        this.pathToZipDestination = pathToZipDestination;
        this.pathToFilesToZip = pathToFilesToZip;
    }

    public void zipFiles() throws Exception{
        FileOutputStream fileWriter = new FileOutputStream(pathToZipDestination);
        this.mZipOutputStream = new ZipOutputStream(fileWriter);
        this.mZipOutputStream.setMethod(Deflater.DEFLATED);
        this.mZipOutputStream.setLevel(8);

        AddFilesToZip("");

        this.mZipOutputStream.finish();
        this.mZipOutputStream.close();
    }

    private void AddFilesToZip(String folder){
        File mFile = new File(pathToFilesToZip + java.io.File.separator + folder);
        String mFiles[] = mFile.list();

        for(String fileName : mFiles){
            File currentFile;
            if(folder != "")
                currentFile = new File(pathToFilesToZip, folder + java.io.File.separator + fileName);
            else
                currentFile = new File(pathToFilesToZip, fileName);
            if(currentFile.isDirectory()){
                if(folder != "")
                    AddFilesToZip(folder + java.io.File.separator + currentFile.getName());
                else
                    AddFilesToZip(currentFile.getName());
            } else {
                try{
                    byte[] buffer = new byte[8000];
                    int len;
                    FileInputStream in = new FileInputStream(currentFile);
                    if(folder != ""){
                        mZipOutputStream.putNextEntry(new ZipEntry(folder + java.io.File.separator + fileName));
                    } else {
                        mZipOutputStream.putNextEntry(new ZipEntry(fileName));
                    }
                    while((len = in.read(buffer)) > 0){
                        mZipOutputStream.write(buffer, 0, len);
                    }
                    mZipOutputStream.closeEntry();
                    in.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
like image 556
Sabastino Avatar asked Jun 08 '13 02:06

Sabastino


People also ask

How do I uncorrupt a DOCX file?

Solution 1: Use the inbuilt Microsoft Word Repair tool Open Microsoft Word and click on File. Click Open and select the . docx file with the problem. Click the down arrow next to the Open button and choose Open and repair.

What causes Zip file corruption?

There are various reasons for a zip file corruption. Incomplete download of a zip file from a website, viruses, file system errors, removable media corruption are some of the causes of zip corruption.

Does zipping a file prevent corruption?

In general if a compressed data stream is corrupted it is not possible for the decompressor to recover, so all data after the point of corruption is likely to be lost. zip compressses each file individually, so the chances are that if a zip file is corrupted only one file will be affected.

Are DOCX files ZIP files?

A Docx file comprises of a collection of XML files that are contained inside a ZIP archive. The contents of a new Word document can be viewed by unzipping its contents. The collection contains a list of XML files that are categorized as: MetaData Files - contains information about other files available in the archive.


1 Answers

I think I've got what's wrong.

When I opened your corrupted File, and opened it on winrar, I saw antislashes at the beginning of the folders, which is unusual:

Content of the corrupted Zip

When I rezip the file after unzipping it, the antislashes are not there anymore and the file opens in Word so I think it should be the issue.

Content of the corrected Zip

I think the code is wrong here:

String outFile = externalPath + java.io.File.separator + fileName;  

should be

if (externalPath=="")
    String outFile = externalPath + fileName;  
else 
    String outFile = externalPath + java.io.File.separator + fileName;  
like image 83
edi9999 Avatar answered Sep 27 '22 02:09

edi9999