我们有一个用例,我们必须通过http将大数据文件从环境A传输到环境B。我们要实现的是,发送方以块的形式发送数据,接收方开始以块的形式将其写入文件。因此,我们决定使用MTOM。
网络服务代码:
@MTOM(enabled = true, threshold=1024)
@WebService(portName = "fileUploadPort", endpointInterface = "com.cloud.receiver.FileUploadService", serviceName = "FileUploadService")
@BindingType(value = SOAPBinding.SOAP12HTTP_MTOM_BINDING)
public class FileUploadServiceImpl implements FileUploadService {
@Override
public void uploadFile(FileUploader Dfile) {
DataHandler handler = Dfile.getFile();
try {
InputStream is = handler.getInputStream();
OutputStream os = new FileOutputStream(new File(absolutePath));
byte[] b = new byte[10000000];
int bytesRead = 0;
while ((bytesRead = is.read(b)) != -1) {
os.write(b, 0, bytesRead);
}
os.flush();
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户代码:
public static void main(String args[]) throws Exception {
URL url = new URL("http://localhost:8080/CloudReceiver/FileUploadService?wsdl");
QName qname = new QName("http://receiver.cloud.com/", "FileUploadService");
Service service = Service.create(url, qname);
FileUploadService port = service.getPort(FileUploadService.class);
// enable MTOM in client
BindingProvider bp = (BindingProvider) port;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
FileUploader f = new FileUploader();
DataSource source = new FileDataSource(new File("G:\\Data\\Sender\\temp.csv"));
DataHandler dh = new DataHandler(source);
Map<String, Object> ctxt = ((BindingProvider) port).getRequestContext();
// Marking Chunk size at Client.
ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 100);
f.setFile(dh);
port.uploadFile(f);
}
当我们传输小于100MB的数据时,一切正常。
超过(100MB +)应用程序服务器(JBoss 8.2)的数据文件在接收器端抛出以下异常。
java.io.IOException: UT000020: Connection terminated as request was larger than 104857600
我理解这个错误是由于standalone.xml中的属性
<http-listener name="default" socket-binding="http" max-post-size="104857600"/>
这意味着数据不会以块的形式写入文件,而是会保存在内存中,然后在传输完成后写入文件。
我们如何实现将数据写入块中?我们不希望增加帖子的内存。文件大小可以达到1 TB。
环境:
JBoss 8.2 Wild Fly,Java 8
最佳答案
首先,提到极限
<http-listener name="default" socket-binding="http" max-post-size="104857600"/>
表示服务器将接受的整个POST请求的最大大小。无论是否使用MTOM,是否使用块,您都只在这里发送带有一个POST请求的文件。使用块不会改变这一点-具有文件数据的所有块都是同一POST请求的一部分。
因此,它可以按预期工作:100M +个文件因限制而过大。
那我很确定这个结论
是完全错误的。在内存中保留潜在的大卷并不安全,因此服务器通常不这样做,而是将这些卷放入一些临时文件中。