35

以下のスニペットのように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ファイルを解凍するように求められるようになりました。助けてください、どうすればさらに進むべきですか?

4

6 に答える 6

23

標準 Java API は、パスワードで保護された zip ファイルをサポートしていません。幸いなことに、善良な人がすでにそのような機能を実装してくれています。パスワードで保護された zip を作成する方法を説明するこの記事をご覧ください。
(リンクは無効で、最新のアーカイブ バージョン: https://web.archive.org/web/20161029174700/http://java.sys-con.com/node/1258827 )

于 2012-05-14T16:52:06.413 に答える
16

以下のサンプル コードは、ファイルを圧縮してパスワードで保護します。この REST サービスは、元のファイルのバイトを受け入れます。バイト配列を圧縮し、パスワードで保護します。次に、パスワードで保護された zip ファイルのバイトを応答として送信します。このコードは、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 を使用しますが、代わりに PUT に HeaderParam を使用して、passwd を見えないようにすることができます。それに応じてテスト方法を変更します。

編集 2 - REST パスは filezip/services/zip/bindata/protect/qparam です

filezip は戦争の名前です。services は、web.xml の URL マッピングです。zip はクラス レベルのパス アノテーションです。binddata/protect/qparam は、メソッド レベルのパス アノテーションです。

于 2015-08-27T15:04:44.100 に答える
1

パスワードで保護されたファイルを作成するためのデフォルトの Java API はありません。ここでそれを行う方法についての別の例があります。

于 2012-05-14T16:54:39.333 に答える
0

ライブラリZip4Jが好ましい答えのようです。パスワードのプライバシーが強く推奨される場合、ZipFile が閉じられた後でも、プレーン テキストclass ZipFileでパスワードを保持する のセキュリティ ギャップを埋めることができます。次のメソッドは、パスワードを破棄します。

public static void destroyZipPassword(ZipFile zip) throws DestroyFailedException
{
    try
    {
        Field fdPwd = ZipFile.class.getDeclaredField("password");
        fdPwd.setAccessible(true);
        char[] password = (char[]) fdPwd.get(zip);
        Arrays.fill(password, (char) 0);
    }
    catch (Exception e)
    {
        e.printStackTrace();
        throw new DestroyFailedException(e.getMessage());
    }
}
于 2021-09-06T09:51:47.347 に答える