2014-12-21 13 views
5

Scala'da bir dizi bayt akışını gerçekleştirmek istediğim Scala'da bir Play Framework uygulaması yapıyorum. Bunu yapmak için Play-S3 kitaplığını kullanıyorum. dokümantasyon bölümünün "Çok parçalı dosya yükleme" Burada alakalı budur: Benim uygulamada ancak Iteratee s ve Enumerator s ile aynı şeyi yapmaya çalışıyorumS3'e Veri Akışı için Oynatma Scala'daki Yineleme ve Numaratörleri Kullanma

// Retrieve an upload ticket 
val result:Future[BucketFileUploadTicket] = 
    bucket initiateMultipartUpload BucketFile(fileName, mimeType) 

// Upload the parts and save the tickets 
val result:Future[BucketFilePartUploadTicket] = 
    bucket uploadPart (uploadTicket, BucketFilePart(partNumber, content)) 

// Complete the upload using both the upload ticket and the part upload tickets 
val result:Future[Unit] = 
    bucket completeMultipartUpload (uploadTicket, partUploadTickets) 

.

dere ve asynchronicity işler biraz karmaşık hale, ama burada (Not uploadTicket kodunda daha önce tanımlanmıştır) bugüne kadar ne var:

val partNumberStream = Stream.iterate(1)(_ + 1).iterator 
val partUploadTicketsIteratee = Iteratee.fold[Array[Byte], Future[Vector[BucketFilePartUploadTicket]]](Future.successful(Vector.empty[BucketFilePartUploadTicket])) { (partUploadTickets, bytes) => 
    bucket.uploadPart(uploadTicket, BucketFilePart(partNumberStream.next(), bytes)).flatMap(partUploadTicket => partUploadTickets.map(_ :+ partUploadTicket)) 
} 
(body |>>> partUploadTicketsIteratee).andThen { 
    case result => 
    result.map(_.map(partUploadTickets => bucket.completeMultipartUpload(uploadTicket, partUploadTickets))) match { 
     case Success(x) => x.map(d => println("Success")) 
     case Failure(t) => throw t 
    } 
} 

Her şey derler ve olaysız çalışır. Aslında, "Success" yazdırılıyor, ancak S3'te hiçbir dosya görünmüyor.

cevap

5

Kodunuzda birden çok sorun olabilir. map yöntem çağrılarının neden olduğu biraz okunamaz. Gelecekteki kompozisyonunuzla ilgili bir probleminiz olabilir. Başka bir sorun, tüm parçaların (sonuncu hariç) en az 5 MB olması gerektiğinden kaynaklanabilir. Aşağıdaki kod sınanmamıştır, ancak farklı bir yaklaşım göstermektedir. Yinelemeli yaklaşım, küçük yapı taşları oluşturabileceğiniz ve bunları bir boru hattına yerleştirebileceğiniz bir yaklaşımdır.

İşte
trait BucketFilePartUploadTicket 
val uploadPart: (Int, Array[Byte]) => Future[BucketFilePartUploadTicket] = ??? 
val completeUpload: Seq[BucketFilePartUploadTicket] => Future[Unit] = ??? 
val body: Enumerator[Array[Byte]] = ??? 

biz

// Create 5MB chunks 
val chunked = { 
    val take5MB = Traversable.takeUpTo[Array[Byte]](1024 * 1024 * 5) 
    Enumeratee.grouped(take5MB transform Iteratee.consume()) 
} 

// Add a counter, used as part number later on 
val zipWithIndex = Enumeratee.scanLeft[Array[Byte]](0 -> Array.empty[Byte]) { 
    case ((counter, _), bytes) => (counter + 1) -> bytes 
} 

// Map the (Int, Array[Byte]) tuple to a BucketFilePartUploadTicket 
val uploadPartTickets = Enumeratee.mapM[(Int, Array[Byte])](uploadPart.tupled) 

// Construct the pipe to connect to the enumerator 
// the ><> operator is an alias for compose, it is more intuitive because of 
// it's arrow like structure 
val pipe = chunked ><> zipWithIndex ><> uploadPartTickets 

// Create a consumer that ends by finishing the upload 
val consumeAndComplete = 
    Iteratee.getChunks[BucketFilePartUploadTicket] mapM completeUpload 

onu Running birkaç parça basitçe parçalarını

// This is the result, a Future[Unit] 
val result = body through pipe run consumeAndComplete 
bağlayarak yapılır oluşturmak Ben bir özelliği ve bir kaç yöntemi eklemiş kod derleme yapmak için

Hiçbir kod test etmediğimi ve yaklaşımımda bazı hatalar yapmış olabileceğimi unutmayın. Ancak bu, problemle baş etmenin farklı bir yolunu gösterir ve muhtemelen iyi bir çözüm bulmanızda size yardımcı olmalıdır.

Bu yaklaşımın, bir sonraki bölümden önce yüklemeyi tamamlamak için bir bölüm beklediğini unutmayın. Sunucunuzdan amazon'a bağlantı, tarayıcıdan sunucuya bağlantıdan daha yavaşsa, bu mekanizma girişi yavaşlatır.

Tamamlanacak bölüm yüklemesinin Future için beklemediğiniz başka bir yaklaşım kullanabilirsiniz. Bu, yükleme sıralarının sırasını, sonuçların bir dizisini içeren tek bir geleceğe dönüştürmek için Future.sequence'u kullandığınız başka bir adımla sonuçlanır. Sonuç, yeterli verilere sahip olduğunuz anda amazon'a bir parça gönderen bir mekanizma olacaktır.

+0

Kodumda her zaman birden çok sorun var. Başka yeni ne var? Ancak, tüm durumlarda parçaların 5 MB olmadığı doğrudur, yani bu bir sorundur. Yine de, fikirlerinizi deneyeceğim ve neler yapabileceğimi göreceğim. – Vidya

İlgili konular