5

EJB サーバー(JBoss)から大きなファイルを取得する必要がある EJB クライアントがあります。

これを実装する明白な方法は、次のようなメソッドを使用して EJB ファサードを提供するサーバーです。

public byte[] getFile(String fileName);

つまり、ファイル全体をメモリ内のバイト配列にロードし、このバイト配列をネットワーク上に送信します。

問題は、このアプローチではファイル全体がメモリに読み込まれることです。ファイルが巨大であるため、オーバーフローする可能性があります。

この問題を克服するオプションはありますか?

4

6 に答える 6

7

HTTP の方が適していますが、次のシリアル化のトリックを試してみてください。

import java.io.*;

public class FileContent implements Serializable {

    private transient File file;

    public FileContent() {
    }

    public FileContent(File file) {
        this.file = file;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        // 1. write the file name
        out.writeUTF(file.getAbsolutePath());

        // 2. write the length
        out.writeLong(file.length());

        // 3. write the content
        final InputStream in = new BufferedInputStream(new FileInputStream(file));
        final byte[] buffer = new byte[1024];

        int length;
        while ((length = in.read(buffer)) != -1) {
            out.write(buffer, 0, length);
        }
        out.flush();
        in.close();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        // 1. read the file name
        final String path = in.readUTF();

        // 2. read the length
        long remaining = in.readLong();

        // 3. read the content
        file = new File(path);
        final OutputStream out = new BufferedOutputStream(new FileOutputStream(file));

        final byte[] buffer = new byte[1024];

        while (true) {
            int length = in.read(buffer, 0, (int) Math.min(remaining, buffer.length));
            if (length == -1) break;

            out.write(buffer, 0, length);

            remaining -= length;
            if (remaining <= 0) break;
        }
        out.flush();
        out.close();
    }
}
于 2012-05-25T01:34:42.763 に答える
5

RMIIOライブラリは、まさにこの状況のた​​めに構築されました。@DavidBlevinsソリューションの実装である DirectRemoteInputStream も含まれています。

于 2012-05-25T02:18:03.950 に答える
2

BytearrayOutputStreamでラップされたZipOutputStreamを使用できます。このアクションにより、RMI送信のオーバーヘッドを減らすために、最初にメソッド宣言を使用して、圧縮されたバイト配列を返すことができます。

于 2012-10-04T07:38:48.930 に答える
1

RMI プロトコルは、大きなファイルを送信するための完全に不適切なソリューションです。可能ではあるが静かで非効率的な解決策は、ファイルを小さなチャンクに分割し、それらを EJB から送信して、クライアント側でファイルを再アセンブルすることです。このようなもの:

public class FileMetadata {
    ....
    private long chunkCount;
    private long chunkSize;
    ....
}

...
public FileMetadata getFileMetadata(String fileName) {...}
public byte[] getFileChunk(String fileName, long chunkNumber) {...}
...
于 2012-05-24T19:40:31.277 に答える
0

私はあなたのアーキテクチャを再考します.ejb呼び出しを迅速に行う必要があります.ejb呼び出しからファイルの場所を返し、別の手順でダウンロードを処理するのはどうですか.大きなファイルをダウンロードする方法の詳細については、こちらをご覧ください. Java を使用してインターネットからファイルをダウンロードして保存するには?

于 2012-10-05T21:22:46.010 に答える