简体   繁体   中英

Unable to create zip file from InputStream

I have a requirement to create a zip file from input stream data, and before writing to zip I need to find the checksum for the input stream.

To do that I am using below codes:

private String writeZipFileToFS(List<ResponsePacks> attachmentList) throws IOException
    {
        File fileToWrite = new File(getZipPath() + "fileName.zip");
        try
        {
            FileUtils.copyInputStreamToFile(compress(attachmentList), fileToWrite);
        }
        catch (IOException e)
        {
            throw e;
        }
        return fileName;
    }

private InputStream compress(List<ResponsePacks> attachmentList)
    {
        byte buffer[] = new byte[2048];
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        ZipOutputStream zipFileToSend = new ZipOutputStream(byteStream);
        try
        {
            for (ResponsePacks info : attachmentList)
            {
                // only for successful requests files would need to be added
                zipFileToSend.putNextEntry(new ZipEntry(info.getFileName()));
                InputStream in = info.getFileContentStream();
                getCheckSum(in, info.getFileName());
                int length;
                while ((length = in.read(buffer)) >= 0)
                {
                    zipFileToSend.write(buffer, 0, length);
                }
                zipFileToSend.closeEntry();
            }
            zipFileToSend.close();
        }
        catch (IOException e)
        {
            throw e;
        }
        return new ByteArrayInputStream(byteStream.toByteArray());
    }
    
    private static void getCheckSum(InputStream is, String fileName)
    {
        byte[] dataCopy = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try
        {
            IOUtils.copy(is, outputStream);
            dataCopy = outputStream.toByteArray();
            printLog("Byte Array Size {}", dataCopy.length);
            String checkSum = calculateChecksum(dataCopy);
            printLog("Checksum for file {} {}", fileName, checkSum);
            outputStream.flush();
            outputStream.close();
        }
        catch (Exception e)
        {
            printLog("Error on calculationg checksum {}", e.getMessage());
        }
    }

    private static String calculateChecksum(byte[] dataCopy)
    {
        try (ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(dataCopy)))
        {
            ZipEntry zipEntry;
            MessageDigest digest = DigestUtils.getSha256Digest();
            DWriter writer = new DWriter(digest);
            while ((zipEntry = zipInputStream.getNextEntry()) != null)
            {
                byte[] entityData = IOUtils.toByteArray(zipInputStream);
                if (!zipEntry.isDirectory())
                {
                    writer.write(entityData);
                }
            }
            if (writer.getChecksum() != null)
            {
                return writer.getChecksum();
            }
        }
        catch (Exception e)
        {
             throw e;
        }
        return "";
    }

static class DWriter
    {
        private final MessageDigest myDigest;

        DWriter(MessageDigest digest)
        {
            myDigest = digest;
        }

        public void write(byte[] data)
        {
            myDigest.update(data);
        }

        public String getChecksum()
        {
            return new String(Hex.encodeHex(myDigest.digest()));
        }
    }

But problem is if I am adding code to calculate the checksum then zip file creating with empty content and if I am removing the checksum calculation code then zip file creating with proper contents.

在此处输入图片说明

And also when I check the log I found InputStream contents different contents but still I am getting the same checkSum (empty string) always as below:

Byte Array Size 20854
Checksum for file 20200910173919142.json e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Byte Array Size 14383
Checksum for file 1599752440405.zip e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

I am unable to find where I am doing wrong, due to which zip file is creating with empty content, and checkSum also creating same always.

Requesting to help me to find where I am doing wrong.

You consume twice the same inputstream: first you read it to get the checksum and the you read it again to write the zip entry.

            getCheckSum(in, info.getFileName());
            int length;
            while ((length = in.read(buffer)) >= 0)
            {
                zipFileToSend.write(buffer, 0, length);
            }

The second time you're trying to read, there's nothing to read anymore, so nothing gets written into the zip entry.

Some input streams can be reset and read multiple times, if that's not the case here you would need to save the data into a ByteArrayOutputStream (as you're already doing inside the getCheckSum() method), and then you could read that data multiple times.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM