我必须传输大文件(500 MB + ...也可以是1GB大小)。这些文件必须是base64编码的,编码的字符串必须放在XML文件中。虽然我的下面的代码适用于较小的文件(30 - 50 MB),但对于大于100 MB的文件,它会失败。 我正在使用SUN的sun64编码器(sun.misc.BASE64Encoder)。
public void execute(InputStream inputstream, OutputStream outputstream) throws StreamTransformationException{
try
{
String sourceFileName = "test_file";
String ReceiverStr = "";
//2. Convert input data in Base64Encoded string
BASE64Encoder encoder = new BASE64Encoder();
byte input[] = new byte[inputstream.available()];
inputstream.read(input);
String base64Encoded = encoder.encode(input);
//3. Build the SOAP request format
String serverUrl = "http://website/url";
String soapEnvelope = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soap=\"http://schemas.microsoft.com/sharepoint/soap/\">";
String soapHeader = "<soapenv:Header/><soapenv:Body><soap:CopyIntoItems><soap:SourceUrl>C:\\Users\\Desktop\\test_file.txt</soap:SourceUrl><soap:DestinationUrls><soap:string>" + serverUrl + "</soap:string></soap:DestinationUrls><soap:Fields><soap:FieldInformation " + "Type=" + "\"Text\"" + " DisplayName=\"" + sourceFileName + "\"" + " InternalName=\"" + sourceFileName + "\"" + " Id=\"deff4b5c-b727-414c-893d-c56a8e12455f\"" + " Value=\"" + sourceFileName + "\"/></soap:Fields>";
String soapStream = "<soap:Stream>" + base64Encoded + "</soap:Stream>";
ReceiverStr = soapEnvelope + soapHeader + soapStream + "</soap:CopyIntoItems></soapenv:Body></soapenv:Envelope>";
//4. Write the SOAP request to receiver channel
outputstream.write(ReceiverStr.getBytes());
}
catch(Exception e) {
throw new StreamTransformationException(e.toString());
}
}
当我尝试在运行时看到该消息时,则不显示整个消息,并在base64Encoded字符串中截断它。 下面是我的系统在执行JAVA代码时看到的错误。 请注意,我的服务器设置可以轻松传输1GB +文件,而不会出现任何JAVA堆大小错误或文件截断。 能告诉我如何使用上述逻辑处理大文件吗?
谢谢,
阿布舍克巴克。
答案 0 :(得分:1)
您的代码存在很多问题。
首先,我建议切换到OutputStreamWriter
而不是OutputStream
作为参数(您不是在写二进制数据,而是在编写字符数据)。
首先写出标题,然后开始处理输入流,例如8192字节(不要使用inputstream.available()
,你不需要它)。如果您不知道处理流的“标准”方式,请浏览Java IO Essentials。基本上你读取了一大块数据,将其转换为Base64
将其写出并重复(直到输入流耗尽)。注意!你必须确保编码大小可被3整除的块(除了最后一个块),否则会应用填充,这会弄乱结果。最后一个块可以有填充。
之后您可以编写页脚,整个过程几乎不会占用任何内存。
答案 1 :(得分:0)
查看代码,将数据存储三次:
第一次是来自输入流的字节数组。第二次是在编码的String中,最后将它写入输出流。
您可以做些什么来优化这一点是将读取与输入流/编码分开,并将编码字符串写入输出流。这样,一旦编码就可以释放输入字节数组,并且可以释放内存。更好的解决方案是编码器直接写入输出流或直接写入encoding output stream。
但是,您仍然需要考虑可以处理的最大文件大小,并相应地调整堆设置:How to deal with "java.lang.OutOfMemoryError: Java heap space" error (64MB heap size)
答案 2 :(得分:-1)
启动应用程序时,您配置了哪种堆大小? 据我所知,默认堆大小为256kb,并且由于您将整个文件一次编码为base64,因此需要将堆大小设置为文件大小的至少1.5倍。
查看如何使用set并使用VM-argument&#34; -Xmx&#34;。