Solución:
Ya que Java 7 (publicado en julio de 2011), hay una mejor manera: Files.copy()
utilidad de java.util.nio.file
.
Copia todos los bytes de un flujo de entrada a un archivo.
Así que tú necesitas ninguno una biblioteca externa ni enrollar sus propios bucles de matriz de bytes. Dos ejemplos a continuación, los cuales usan el flujo de entrada de S3Object.getObjectContent()
.
InputStream in = s3Client.getObject("bucketName", "key").getObjectContent();
1) Escriba en un nuevo archivo en la ruta especificada:
Files.copy(in, Paths.get("/my/path/file.jpg"));
2) Escriba en un archivo temporal en la ubicación tmp predeterminada del sistema:
File tmp = File.createTempFile("s3test", "");
Files.copy(in, tmp.toPath(), StandardCopyOption.REPLACE_EXISTING);
(Sin especificar la opción para reemplazar el archivo existente, obtendrá un FileAlreadyExistsException
.)
También tenga en cuenta que getObjectContent()
Javadocs te insta a cerrar el flujo de entrada:
Si recupera un S3Object, debe cerrar este flujo de entrada lo antes posible, porque el contenido del objeto no se almacena en búfer en la memoria y se transmite directamente desde Amazon S3. Además, si no se cierra esta secuencia, se puede bloquear el grupo de solicitudes.
Por lo tanto, debería ser más seguro envolver todo en try-catch-finalmente y hacer in.close();
en el bloque finalmente.
Lo anterior asume que usa el SDK oficial de Amazon (aws-java-sdk-s3
).
Tiempo IOUtils.copy()
y IOUtils.copyLarge()
son geniales, preferiría la forma de la vieja escuela de recorrer el flujo de entrada hasta que el flujo de entrada devuelva -1. ¿Por qué? Usé IOUtils.copy () antes, pero hubo un caso de uso específico en el que si comenzaba a descargar un archivo grande de S3 y luego, por alguna razón, si ese hilo se interrumpía, la descarga no se detenía y seguía y seguía hasta que se descargó el archivo completo.
Por supuesto, esto no tiene nada que ver con S3, solo la biblioteca IOUtils.
Entonces, prefiero esto:
InputStream in = s3Object.getObjectContent();
byte[] buf = new byte[1024];
OutputStream out = new FileOutputStream(file);
while( (count = in.read(buf)) != -1)
{
if( Thread.interrupted() )
{
throw new InterruptedException();
}
out.write(buf, 0, count);
}
out.close();
in.close();
Nota: esto también significa que no necesita bibliotecas adicionales
La clase AmazonS3Client tiene el siguiente método:
S3Object getObject(String bucketName, String key)
El S3Object devuelto tiene el método …
java.io.InputStream getObjectContent()
..que obtiene el contenido del objeto como una secuencia. Usaría IOUtils de Apache Commons así:
IOUtils.copy(s3Object.getObjectContent(), new FileOutputStream(new File(filepath)));