java中受密码保护的zip文件

时间:2012-05-14 16:42:37

标签: java zip

我使用java创建了zip文件,如下面的代码段

import java.io.*;
import java.util.zip.*;

public class ZipCreateExample {
  public static void main(String[] args) throws IOException {
    System.out.print("Please enter file name to zip : ");
    BufferedReader input = new BufferedReader
        (new InputStreamReader(System.in));
    String filesToZip = input.readLine();
    File f = new File(filesToZip);
    if(!f.exists()) {
      System.out.println("File not found.");
      System.exit(0);
    }
    System.out.print("Please enter zip file name : ");
    String zipFileName = input.readLine();
    if (!zipFileName.endsWith(".zip"))
      zipFileName = zipFileName + ".zip";
    byte[] buffer = new byte[18024];
    try {
      ZipOutputStream out = new ZipOutputStream
          (new FileOutputStream(zipFileName));
      out.setLevel(Deflater.DEFAULT_COMPRESSION);
      FileInputStream in = new FileInputStream(filesToZip);
      out.putNextEntry(new ZipEntry(filesToZip));
      int len;
      while ((len = in.read(buffer)) > 0) {
        out.write(buffer, 0, len);
      }
      out.closeEntry();
      in.close();
      out.close();
    } catch (IllegalArgumentException iae) {
      iae.printStackTrace();
      System.exit(0);
    } catch (FileNotFoundException fnfe) {
      fnfe.printStackTrace();
      System.exit(0);
    } catch (IOException ioe) {
      ioe.printStackTrace();
      System.exit(0);
    }
  }
}

现在我想要点击zip文件时它应该提示我输入密码然后解压缩zip文件。 请帮忙,我该怎么走?

5 个答案:

答案 0 :(得分:19)

标准Java API不支持受密码保护的zip文件。幸运的是,好人已经为我们实现了这样的能力。请查看本文,其中介绍了如何创建受密码保护的zip:http://java.sys-con.com/node/1258827

答案 1 :(得分:13)

尝试以下基于Zip4j的代码:

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.io.FilenameUtils;

import java.io.File;

public class Zipper
{
    private String password;
    private static final String EXTENSION = "zip";

    public Zipper(String password)
    {
        this.password = password;
    }

    public void pack(String filePath) throws ZipException
    {
        ZipParameters zipParameters = new ZipParameters();
        zipParameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        zipParameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_ULTRA);
        zipParameters.setEncryptFiles(true);
        zipParameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
        zipParameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
        zipParameters.setPassword(password);
        String baseFileName = FilenameUtils.getBaseName(filePath);
        String destinationZipFilePath = baseFileName + "." + EXTENSION;
        ZipFile zipFile = new ZipFile(destinationZipFilePath);
        zipFile.addFile(new File(filePath), zipParameters);
    }

    public void unpack(String sourceZipFilePath, String extractedZipFilePath) throws ZipException
    {
        ZipFile zipFile = new ZipFile(sourceZipFilePath + "." + EXTENSION);

        if (zipFile.isEncrypted())
        {
            zipFile.setPassword(password);
        }

        zipFile.extractAll(extractedZipFilePath);
    }
}

FilenameUtils来自Apache Commons IO

使用示例:

public static void main(String[] arguments) throws ZipException
{
    Zipper zipper = new Zipper("password");
    zipper.pack("encrypt-me.txt");
    zipper.unpack("encrypt-me", "D:\\");
}

答案 2 :(得分:10)

下面的示例代码将压缩和密码保护您的文件。 此REST服务接受原始文件的字节。它压缩字节数组,密码保护它。然后它发送密码保护的压缩文件的字节作为响应。该代码是向REST服务发送和接收二进制字节的示例,也是使用密码保护压缩文件的示例。字节从流中压缩,因此服务器上不会存储任何文件。

  • 在java中使用Jersey API使用JAX-RS API
  • 客户端正在使用Jersey-client API。
  • 使用zip4j 1.3.2开源库和apache commons io。


    @PUT
    @Path("/bindata/protect/qparam")
    @Consumes(MediaType.APPLICATION_OCTET_STREAM)
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response zipFileUsingPassProtect(byte[] fileBytes, @QueryParam(value = "pass") String pass,
            @QueryParam(value = "inputFileName") String inputFileName) {

        System.out.println("====2001==== Entering zipFileUsingPassProtect");
        System.out.println("fileBytes size = " + fileBytes.length);
        System.out.println("password = " + pass);
        System.out.println("inputFileName = " + inputFileName);

        byte b[] = null;
        try {
            b = zipFileProtected(fileBytes, inputFileName, pass);
        } catch (IOException e) {
            e.printStackTrace();
            return Response.status(Status.INTERNAL_SERVER_ERROR).build();
        }
        System.out.println(" ");
        System.out.println("++++++++++++++++++++++++++++++++");
        System.out.println(" ");
        return Response.ok(b, MediaType.APPLICATION_OCTET_STREAM)
                .header("content-disposition", "attachment; filename = " + inputFileName + ".zip").build();

    }

    private byte[] zipFileProtected(byte[] fileBytes, String fileName, String pass) throws IOException {

        ByteArrayInputStream inputByteStream = null;
        ByteArrayOutputStream outputByteStream = null;
        net.lingala.zip4j.io.ZipOutputStream outputZipStream = null;

        try {
            //write the zip bytes to a byte array
            outputByteStream = new ByteArrayOutputStream();
            outputZipStream = new net.lingala.zip4j.io.ZipOutputStream(outputByteStream);

            //input byte stream to read the input bytes
            inputByteStream = new ByteArrayInputStream(fileBytes);

            //init the zip parameters
            ZipParameters zipParams = new ZipParameters();
            zipParams.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            zipParams.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
            zipParams.setEncryptFiles(true);
            zipParams.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
            zipParams.setPassword(pass);
            zipParams.setSourceExternalStream(true);
            zipParams.setFileNameInZip(fileName);

            //create zip entry
            outputZipStream.putNextEntry(new File(fileName), zipParams);
            IOUtils.copy(inputByteStream, outputZipStream);
            outputZipStream.closeEntry();

            //finish up
            outputZipStream.finish();

            IOUtils.closeQuietly(inputByteStream);
            IOUtils.closeQuietly(outputByteStream);
            IOUtils.closeQuietly(outputZipStream);

            return outputByteStream.toByteArray();

        } catch (ZipException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(inputByteStream);
            IOUtils.closeQuietly(outputByteStream);
            IOUtils.closeQuietly(outputZipStream);
        }
        return null;
    }

下面的单元测试:


    @Test
    public void testPassProtectZip_with_params() {
        byte[] inputBytes = null;
        try {
            inputBytes = FileUtils.readFileToByteArray(new File(inputFilePath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("bytes read into array. size = " + inputBytes.length);

        Client client = ClientBuilder.newClient();

        WebTarget target = client.target("http://localhost:8080").path("filezip/services/zip/bindata/protect/qparam");
        target = target.queryParam("pass", "mypass123");
        target = target.queryParam("inputFileName", "any_name_here.pdf");

        Invocation.Builder builder = target.request(MediaType.APPLICATION_OCTET_STREAM);

        Response resp = builder.put(Entity.entity(inputBytes, MediaType.APPLICATION_OCTET_STREAM));
        System.out.println("response = " + resp.getStatus());
        Assert.assertEquals(Status.OK.getStatusCode(), resp.getStatus());

        byte[] zipBytes = resp.readEntity(byte[].class);
        try {
            FileUtils.writeByteArrayToFile(new File(responseFilePathPasswordZipParam), zipBytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

随意使用和修改。如果您发现任何错误,请告诉我。希望这可以帮助。

编辑1 - 使用QueryParam,但您可以使用HeaderParam进行PUT,而不是隐藏passwd。相应地修改测试方法。

编辑2 - REST路径是filezip / services / zip / bindata / protect / qparam

filezip是战争的名称。 services是web.xml中的url映射。 zip是类级别路径注释。 bindata / protect / qparam是方法级别路径注释。

答案 3 :(得分:1)

没有默认的Java API来创建受密码保护的文件。关于如何做到这一点有另一个例子here

答案 4 :(得分:0)

在新版本的 Zip4j 中,类 Zip4jConstants 被删除。请改用 EncryptionMethod AesKeyStrength 类。文档:https://github.com/srikanth-lingala/zip4j

ZipParameters zipParameters = new ZipParameters();
zipParameters.setEncryptFiles(true);
zipParameters.setEncryptionMethod(EncryptionMethod.AES);
zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256); 

List<File> filesToAdd = Arrays.asList(
    new File("somefile"), 
    new File("someotherfile")
);

ZipFile zipFile = new ZipFile("filename.zip", "password".toCharArray());
zipFile.addFiles(filesToAdd, zipParameters);