web-dev-qa-db-fra.com

Comment définir la longueur du contenu InputStream

Je télécharge des fichiers vers un compartiment Amazon S3. Les fichiers sont en cours de téléchargement, mais je reçois l'avertissement suivant. 

AVERTISSEMENT: Aucune longueur de contenu spécifiée pour les données de flux. Contenu du flux sera mis en mémoire tampon et pourrait entraîner des erreurs de mémoire insuffisante.

J'ai donc ajouté la ligne suivante à mon code

metaData.setContentLength(IOUtils.toByteArray(input).length);

mais alors j'ai eu le message suivant. Je ne sais même pas si c'est un avertissement ou quoi. 

Les données lues ont une longueur différente de celle attendue: dataLength = 0; longueur attendue = 111992; includeSkipped = false; in.getClass () = class Sun.net.httpserver.FixedLengthInputStream; marquéeSupporté = faux; marqué = 0; resetSinceLastMarked = false; markCount = 0; resetCount = 0

Comment puis-je définir contentLength sur la métaData de InputSteam? Toute aide serait grandement appréciée.

13
Shaonline

Lorsque vous lisez les données avec IOUtils.toByteArray, cela utilise le flux InputStream. Lorsque l'API AWS essaie de le lire, sa longueur est nulle.

Lisez le contenu dans un tableau d'octets et fournissez un InputStream enveloppant ce tableau à l'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);
20
ataylor

Dernières nouvelles! AWS SDK 2.0 prend en charge le téléchargement de fichiers:

        s3client.putObject(
                (builder) -> builder.bucket(myBucket).key(file.getName()),
                RequestBody.fromFile(file)
        );

Il existe également des méthodes RequestBody pour prendre des chaînes ou des tampons qui définissent automatiquement et efficacement Content-Length. Ce n'est que lorsque vous utilisez un autre type de InputStream que vous devez indiquer vous-même la longueur. Toutefois, ce cas devrait être plus rare maintenant avec toutes les autres options disponibles.

0
Robert Jack Will

Notez qu'en utilisant un ByteBuffer, vous faites simplement ce que le kit AWS SDK a déjà fait pour vous automatiquement! Il met toujours en mémoire tampon le flux entier et correspond à la solution d'origine qui génère l'avertissement à partir du SDK.

Vous ne pouvez supprimer le problème de mémoire que si vous disposez d'un autre moyen de connaître la longueur du flux, par exemple lorsque vous créez le flux à partir d'un fichier:

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)
        );
    }
}
0
Robert Jack Will