我想使用Apache的HttpClient
类(4.1.2)将非常大的文件(最多5或6 GB)上传到Web服务器。在发送这些文件之前,我将它们分成更小的块(例如100 MB)。不幸的是,我看到使用HttpClient
进行多部分POST的所有示例似乎都在发送文件内容之前缓冲文件内容(通常假设文件大小很小)。这是一个例子:
HttpClient httpclient = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.example.com/upload.php");
MultipartEntity mpe = new MultipartEntity();
// Here are some plain-text fields as a part of our multi-part upload
mpe.addPart("chunkIndex", new StringBody(Integer.toString(chunkIndex)));
mpe.addPart("fileName", new StringBody(somefile.getName()));
// Now for a file to include; looks like we're including the whole thing!
FileBody bin = new FileBody(new File("/path/to/myfile.bin"));
mpe.addPart("myFile", bin);
post.setEntity(mpe);
HttpResponse response = httpclient.execute(post);
在此示例中,我们似乎创建了一个新的FileBody
对象并将其添加到MultipartEntity
。在我的情况下,文件大小可能是100 MB,我宁愿不一次缓冲所有数据。我希望能够以较小的块(例如,每次4 MB)写出数据,最终写入所有100 MB。我可以使用Java中的HTTPURLConnection
类(通过直接写入输出流)来执行此操作,但该类有自己的一组问题,这就是我尝试使用Apache产品的原因。
是否可以向HttpClient写入100 MB的数据,但是在较小的迭代块中?我不希望客户端在实际执行POST之前必须缓冲多达100 MB的数据。我看到的所有示例似乎都不允许您直接写入输出流;他们似乎都在execute()
电话会议之前预先打包。
任何提示都将不胜感激!
为了澄清,这是我之前使用HTTPURLConnection
课程所做的事情。我正在试图弄清楚如何在HttpClient
中执行类似操作:
// Get the connection's output stream
out = new DataOutputStream(conn.getOutputStream());
// Write some plain-text multi-part data
out.writeBytes(fieldBuffer.toString());
// Figure out how many loops we'll need to write the 100 MB chunk
int bufferLoops = (dataLength + (bufferSize - 1)) / bufferSize;
// Open the local file (~5 GB in size) to read the data chunk (100 MB)
raf = new RandomAccessFile(file, "r");
raf.seek(startingOffset); // Position the pointer to the beginning of the chunk
// Keep track of how many bytes we have left to read for this chunk
int bytesLeftToRead = dataLength;
// Write the file data block to the output stream
for(int i=0; i<bufferLoops; i++)
{
// Create an appropriately sized mini-buffer (max 4 MB) for the pieces
// of this chunk we have yet to read
byte[] buffer = (bytesLeftToRead < bufferSize) ?
new byte[bytesLeftToRead] : new byte[bufferSize];
int bytes_read = raf.read(buffer); // Read ~4 MB from the local file
out.write(buffer, 0, bytes_read); // Write that bit to the stream
bytesLeftToRead -= bytes_read;
}
// Write the final boundary
out.writeBytes(finalBoundary);
out.flush();
答案 0 :(得分:0)
如果我正确理解你的问题,你关注的是将整个文件加载到内存中(对吗?)。如果是这种情况,您应该使用Streams(例如FileInputStream)。这样,整个文件不会立即被拉入内存。
如果这没有帮助,并且您仍然希望将文件分成块,则可以对服务器进行编码以处理多个POSTS,在获取数据时将数据连接起来,然后手动分割数据。文件。
就我个人而言,我更喜欢我的第一个答案,但无论哪种方式(或者如果这些都没有帮助,都不会这样),祝你好运!
答案 1 :(得分:0)
Streams肯定是要走的路,我记得做了类似的事情,回到一些更大的文件,它工作得很好。
答案 2 :(得分:0)
您只需将自定义内容生成逻辑包装到HttpEntity
实现中即可。这将使您完全控制内容生成和内容流的过程。
对于记录:MultipartEntity
附带HttpClient
在将文件写入连接套接字之前不会将文件部分缓冲在内存中。