0

SO のいくつかの例に従って、zip から画像ファイルを取得し、各ファイルのバイトをハッシュマップに入れます。

final byte[] zip_file = ((CommonsMultipartFile) zip_file).getBytes();
zip_stream = new ZipInputStream(new ByteArrayInputStream(zip_file));

try {
    while ((entry = zip_stream.getNextEntry()) != null) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            BufferedOutputStream dest = new BufferedOutputStream(baos, BUFFER_SIZE);
                try {
                    int count = 0;
                    byte[] data = new byte[BUFFER_SIZE];

                    while ((count = zip_stream.read(data, 0, BUFFER_SIZE)) > 0) {
                        dest.write(data, 0, count);
                    }

                    dest.flush();

                    filelist.put(entry.getName(), baos.toByteArray());
                    baos.reset();
                } finally {
                    dest.close();
                }
            } finally {
                baos.close();
            }
        }
    } finally {
        zip_stream.close();
    }

後で から読み取るfilelistと、バイト配列は次のように Java Bean に保持されます。

Customer customer = new Customer();
byte[] image = fileist.get(imageFileName);
customer.setImage(image);

Customerimageフィールドが型を持つ JPA エンティティです@Lob。したがって、この部分は問題にならないはずです。

悲しいパーティーは、トランザクション全体の後に「イメージ」フィールドにいくつかのデータが書き込まれたが、Oracle から (SQL 開発者を使用して) バイトをイメージ ファイルに構成できないことです。つまり、Oracle からファイルが壊れています。バイトが破損する原因が何かあるはずです。どうすればそれを機能させることができますか?

アップデート

inputstream-outputstream transfer を使用して変更しますIOUtils.copyが、まだ機能していません...しかし、ここで何か問題があると感じていますが、修正方法がわかりません。次のコードでは、zipInputStream の各エントリでループが機能しているように見えます。エントリはファイル名の代わりにアクセスされることはありません。正常に見えますか?

 try {
        while ((entry = zip_stream.getNextEntry()) != null) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                IOUtils.copy(zip_stream, baos);
            } finally {
                baos.close();
            }
            filelist.put(entry.getName(), baos.toByteArray());
        }
    } finally {
        zip_stream.close();
    }
4

1 に答える 1

1

baos.set を削除し、filelist.put を baos.close の後に移動します。

正直なところ、 dest と baos を逆にネストする必要があり、 dest.close で十分であり、baos を閉じることを意味すると思います。

また、getBytes の代わりに getInputStream を実行することもできます。

確かに;を持つIOUtilsがあります。copyどこかに「開いたままにする」というフラグが付いたコピーがあるはずです。


ディレクトリ エントリはスキップされず、closeEntry は呼び出されませんでした。

    try {
        ZipInputStream zipInputStream = new ZipInputStream(
            new FileInputStream("D:/dev/... .zip"));
        ZipEntry zipEntry;
        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
            System.out.println("- " + zipEntry.getName()
                + " #" + zipEntry.getSize());
            if (zipEntry.isDirectory()) {
                zipInputStream.closeEntry();
                continue;
            }

            long size = zipEntry.getSize();
            if (size > Integer.MAX_VALUE) {
                throw new IOException("File too large: " + zipEntry.getName());
            }
            int reserved = size == -1L ? 8192 : (int)size; 
            ByteArrayOutputStream baos = new ByteArrayOutputStream(reserved);
            IOUtils.copy(zipInputStream, baos);
            zipInputStream.closeEntry();

            baos.close();
            File file = new File("D:/dev/data/temp/" + zipEntry.getName());
            file.getParentFile().mkdirs();
            FileUtils.writeByteArrayToFile(file, baos.toByteArray());
        }
    } catch (IOException ex) {
        Logger.getLogger(Stackoverflow.class.getName()).log(Level.SEVERE, null, ex);
    }
于 2013-05-28T14:45:46.263 に答える