Проблема
Я хотел бы загрузить очень большие файлы (до 5 или 6 ГБ) на веб-сервер, используя класс HttpClient
(4.1.2) из Apache.Перед отправкой этих файлов я разбиваю их на более мелкие куски (например, 100 МБ).К сожалению, все примеры, которые я вижу для выполнения POST из нескольких частей с использованием HttpClient
, по-видимому, буферизуют содержимое файла перед отправкой (обычно предполагается небольшой размер файла).Вот такой пример:
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 МБ, я бы предпочел не буферизовать все эти данные сразу.Я хотел бы иметь возможность записывать эти данные небольшими порциями (например, 4 МБ за раз), в конечном итоге записывая все 100 МБ.Я могу сделать это, используя класс HTTPURLConnection
из Java (путем записи непосредственно в выходной поток), но у этого класса есть свой собственный набор проблем, поэтому я пытаюсь использовать предложения Apache.
Мой вопрос
Можно ли записать 100 МБ данных в HttpClient, но небольшими итеративными блоками?Я не хочу, чтобы клиенту пришлось буферизовать до 100 МБ данных перед тем, как делать POST.Кажется, что ни один из примеров, которые я вижу, не позволяет вам писать напрямую в выходной поток;все они, кажется, предварительно упаковывают вещи перед 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();