Je souhaite télécharger des fichiers volumineux à partir de Google Cloud Storage à l'aide de la bibliothèque Java fournie par google com.google.cloud.storage. J'ai le code de travail, mais j'ai toujours une question et une préoccupation majeure:Comment télécharger un gros fichier à partir de Google Cloud Storage à l'aide de Java avec contrôle de total de contrôle
Ma principale préoccupation est, quand est le contenu du fichier réellement téléchargé? Pendant (références au code ci-dessous) storage.get(blobId)
, pendant blob.reader()
ou pendant reader.read(bytes)
? Cela devient très important quand il s'agit de comment gérer une somme de contrôle invalide, que dois-je faire pour déclencher réellement que le fichier est récupéré sur le réseau à nouveau?
La question la plus simple est la suivante: y a-t-il une fonctionnalité intégrée permettant de vérifier md5 (ou crc32c) sur le fichier reçu dans la bibliothèque google? Peut-être que je n'ai pas besoin de l'implémenter tout seul.
Voici ma méthode tente de télécharger des fichiers volumineux de Google Cloud Storage:
private static final int MAX_NUMBER_OF_TRIES = 3;
public Path downloadFile(String storageFileName, String bucketName) throws IOException {
// In my real code, this is a field populated in the constructor.
Storage storage = Objects.requireNonNull(StorageOptions.getDefaultInstance().getService());
BlobId blobId = BlobId.of(bucketName, storageFileName);
Path outputFile = Paths.get(storageFileName.replaceAll("/", "-"));
int retryCounter = 1;
Blob blob;
boolean checksumOk;
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
do {
LOGGER.debug("Start download file {} from bucket {} to Content Store (try {})", storageFileName, bucketName, retryCounter);
blob = storage.get(blobId);
if (null == blob) {
throw new CloudStorageCommunicationException("Failed to download file after " + retryCounter + " tries.");
}
if (Files.exists(outputFile)) {
Files.delete(outputFile);
}
try (ReadChannel reader = blob.reader();
FileChannel channel = new FileOutputStream(outputFile.toFile(), true).getChannel()) {
ByteBuffer bytes = ByteBuffer.allocate(128 * 1024);
int bytesRead = reader.read(bytes);
while (bytesRead > 0) {
bytes.flip();
messageDigest.update(bytes.array(), 0, bytesRead);
channel.write(bytes);
bytes.clear();
bytesRead = reader.read(bytes);
}
}
String checksum = Base64.encodeBase64String(messageDigest.digest());
checksumOk = checksum.equals(blob.getMd5());
if (!checksumOk) {
Files.delete(outputFile);
messageDigest.reset();
}
} while (++retryCounter <= MAX_NUMBER_OF_TRIES && !checksumOk);
if (!checksumOk) {
throw new CloudStorageCommunicationException("Failed to download file after " + MAX_NUMBER_OF_TRIES + " tries.");
}
return outputFile;
}
C'est logique! Si je détecte une somme de contrôle non valide, existe-t-il un moyen de forcer la bibliothèque com.google.cloud.storage à télécharger à nouveau le fichier et à ne pas le récupérer dans un cache? –
Je ne voudrais pas déranger. Si vous obtenez une somme de contrôle invalide, l'erreur était très susceptible d'être un problème de réseau, et cela n'arrivera pas la deuxième fois. En outre, les lectures HTTPS faites avec des informations d'identification ne seront certainement pas mises en cache à moins que vous soyez derrière un pare-feu d'entreprise particulièrement bizarre. Néanmoins, vous pouvez certainement ignorer la plupart des caches en ajoutant simplement un paramètre d'URL non-sens supplémentaire, comme "& skipCaching = 12345". –
Le problème n'est pas le cache HTTP, mais le cache dans la bibliothèque Java fourni par google (lien dans la question ci-dessus). JavaDoc for ReadChannel indique que "les implémentations de cette classe peuvent tamponner les données en interne pour réduire les appels distants". Voici une page qui parle de la validation de la somme de contrôle, mais qui ne répond pas à ma question pour autant que je puisse la voir: https://cloud.google.com/storage/docs/hashes-etags Je ne travaille donc pas directement avec les URLs malheureusement. –