[英]Returning huge file from a remote EJB call
我有一个EJB客户端需要从EJB服务器 (JBoss)检索一个大文件 。
实现这一点的明显方法是使用如下方法提供EJB外观的服务器:
public byte[] getFile(String fileName);
这意味着, 将整个文件加载到内存中 ,以字节数组形式,然后在线路上发送此字节数组。
问题是这种方法将整个文件加载到内存中,并且由于文件很大,它会溢出它。
有没有选择来克服这个问题?
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();
}
}
RMIIO库就是针对这种情况而构建的。 它甚至包括@DavidBlevins解决方案的实现,即DirectRemoteInputStream 。
您可以使用ZipOutputStream,它包含在BytearrayOutputStream中。 此操作将允许您首先使用方法声明返回压缩字节数组,以减少RMI传输的开销。
RMI协议是发送大文件的完全错误的解决方案。 一个可能但安静的低效解决方案是将文件分成小块,从EJB发送它们并在客户端重新组装文件。 像这样的东西:
public class FileMetadata {
....
private long chunkCount;
private long chunkSize;
....
}
...
public FileMetadata getFileMetadata(String fileName) {...}
public byte[] getFileChunk(String fileName, long chunkNumber) {...}
...
我会重新考虑你的架构,恕我直言你应该快速保持你的ejb调用,如何从ejb调用返回文件的位置然后在另一个程序中处理downlod,看看这里有关如何下载大文件的更多信息使用Java从Internet下载并保存文件?
我采用的方法(介意你只适用于@LocalBean
)是从EJB写入File.createTempFile
并返回一个File
来检索数据并从客户端删除它。 Path
也可以使用,但请注意它不是可Serializable
。
但是,您也可以将其写入由HTTP服务器托管的文件,并在以后从那里检索它。 然后发送HTTP DELETE
请求以删除文件。 您的EJB将返回java.net.URI
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.