Как установить содержимое InputStream Длина
Я загружаю файлы в ведро Amazon S3. Файлы загружаются, но я получаю следующее предупреждение.
ПРЕДУПРЕЖДЕНИЕ: для данных потока не указана длина содержимого. Содержимое потока будет буферизован в памяти и может привести к ошибкам памяти.
Итак, я добавил следующую строку в свой код
metaData.setContentLength(IOUtils.toByteArray(input).length);
но затем я получил следующее сообщение. Я даже не знаю, это предупреждение или что.
Чтение данных имеет разную длину, чем ожидалось: dataLength = 0; expectedLength = 111992; includeSkipped = ложь; in.getClass() = класс sun.net.httpserver.FixedLengthInputStream; markedSupported = ложь; отмеченные = 0; resetSinceLastMarked = ложь; markCount = 0; resetCount = 0
Как я могу установить contentLength для метаданных InputSteam? Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Когда вы читаете данные с помощью IOUtils.toByteArray
, это потребляет InputStream. Когда AWS API пытается его прочитать, это нулевая длина.
Прочитайте содержимое в массив байтов и предоставьте пакет InputStream, который этот массив применяет к API:
byte[] bytes = IOUtils.toByteArray(input);
metaData.setContentLength(bytes.length);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, byteArrayInputStream, metadata);
client.putObject(putObjectRequest);
Ответ 2
Обратите внимание, что с помощью ByteBuffer вы просто делаете вручную то, что AWS SDK уже сделал для вас автоматически! Он по-прежнему буферизует весь поток в память и так же хорош, как и оригинальное решение, которое выдает предупреждение из SDK.
Вы можете избавиться от проблемы с памятью, только если у вас есть другой способ узнать длину потока, например, когда вы создаете поток из файла:
void uploadFile(String bucketName, File file) {
try (final InputStream stream = new FileInputStream(file)) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.length());
s3client.putObject(
new PutObjectRequest(bucketName, file.getName(), stream, metadata)
);
}
}
Ответ 3
Последние новости! AWS SDK 2.0 имеет встроенную поддержку для загрузки файлов:
s3client.putObject(
(builder) -> builder.bucket(myBucket).key(file.getName()),
RequestBody.fromFile(file)
);
Есть также методы RequestBody
для получения строк или буферов, которые автоматически и эффективно устанавливают Content-Length. Только когда у вас есть другой тип InputStream, вам все равно нужно указывать длину самостоятельно - однако этот случай должен быть более редким сейчас со всеми другими доступными опциями.