in app/helpers/StorageHelper.scala [198:259]
def copyAssetFolderFile(sourceFile: AssetFolderFileEntry, destFile:AssetFolderFileEntry)
(implicit db:slick.jdbc.PostgresProfile#Backend#Database):Future[AssetFolderFileEntry] = {
logger.debug(s"copyAssetFolderFile running with source of $sourceFile")
def getStorageDriverForFile(file:AssetFolderFileEntry) = {
file
.storage
.map(_.flatMap(_.getStorageDriver))
.map({
case Some(storageDriver) => storageDriver
case None => throw new RuntimeException(s"Storage with id. ${file.storageId} does not have a valid storage type")
})
}
def withReadStream[A](sourceFile:AssetFolderFileEntry)(cb:(Option[StorageMetadata], InputStream)=>Try[A]) = {
val readStreamFut = for {
driver <- getStorageDriverForFile(sourceFile)
fullPath <- sourceFile.getFullPath
readStream <- Future.fromTry(driver.getReadStream(fullPath, sourceFile.version))
meta <- Future.fromTry(Try { driver.getMetadata(fullPath, sourceFile.version)})
} yield (driver, readStream, meta)
readStreamFut.map({
case (driver, readStream, meta)=>
val result = cb(meta, readStream)
Try { readStream.close() } match {
case Success(_)=>
case Failure(err)=>
logger.error(s"Could not close file $sourceFile via driver $driver: ${err.getMessage}", err)
}
Future.fromTry(result)
}).flatten
}
val destination = for {
destFilePath <- destFile.getFullPath
destStorageDriver <- getStorageDriverForFile(destFile)
} yield (destFilePath, destStorageDriver)
destination.flatMap({
case (destFilePath, destDriver)=>
withReadStream(sourceFile) { (sourceMeta,readStream)=>
destDriver
.writeDataToPath(destFilePath, destFile.version, readStream)
.flatMap(_=> {
//Now that the copy completed successfully, we need to check that the file sizes actually match
destDriver.getMetadata(destFilePath, destFile.version) match {
case None =>
logger.error(s"${sourceFile.filepath}: Could not get destination file metadata")
Failure(new RuntimeException(s"${sourceFile.filepath}: Could not get destination file metadata"))
case Some(meta)=>
logger.debug(s"${sourceFile.filepath}: Destination size is ${meta.size} and source size is ${sourceMeta.get.size}")
if(meta.size==sourceMeta.get.size) {
Success( () )
} else {
Failure(new RuntimeException(s"${sourceFile.filepath}: Copied file size ${meta.size} did not match source size of ${sourceMeta.get.size}"))
}
}
})
}.map(_=>destFile.copy())
})
}