2014-12-21 4 views
5

मैं स्काला में एक प्ले फ्रेमवर्क आवेदन के निर्माण कर रहा हूँ करने के लिए डेटा स्ट्रीम करने के लिए जहाँ मैं S3 बाइट्स की एक सरणी स्ट्रीम करने के लिए करना चाहते हैं। मैं ऐसा करने के लिए Play-S3 लाइब्रेरी का उपयोग कर रहा हूं। प्रलेखन अनुभाग के "मल्टीपार्ट फाइल अपलोड" क्या यहाँ प्रासंगिक है:प्ले स्काला में Iteratees और ूगणकों का प्रयोग S3

// 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) 

मैं अपने आवेदन में लेकिन Iteratee और Enumerator के साथ एक ही बात करने के लिए कोशिश कर रहा हूँ।

नदियों और asynchronicity बातें थोड़ा जटिल है, लेकिन यहाँ मैं अब तक (ध्यान दें uploadTicket कोड में पहले परिभाषित किया गया है) क्या है:

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 
    } 
} 

सब कुछ संकलित करता है तथा घटना के बिना चलाता है। वास्तव में, "Success" मुद्रित हो जाता है, लेकिन कोई फ़ाइल कभी भी S3 पर दिखाई नहीं देती है।

उत्तर

5

वहाँ अपने कोड के साथ कई समस्याएं हो सकती है। यह map विधि कॉल के कारण थोड़ा अपठनीय है। आपको भविष्य की रचना के साथ समस्या हो सकती है। एक और समस्या इस तथ्य के कारण हो सकती है कि सभी हिस्सों (अंतिम को छोड़कर) कम से कम 5 एमबी होना चाहिए।

कोड के नीचे परीक्षण नहीं किया गया है, लेकिन एक अलग दृष्टिकोण को दर्शाता है। Iteratee दृष्टिकोण वह है जहां आप छोटे बिल्डिंग ब्लॉक बना सकते हैं और उन्हें संचालन की पाइप में बना सकते हैं।

कोड संकलन मैं एक विशेषता है और कुछ विधियां जोड़ बनाने के

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

यहाँ हम कुछ भागों

// 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 

यह चल रहा है बस भागों

// This is the result, a Future[Unit] 
val result = body through pipe run consumeAndComplete 
जोड़ने के द्वारा किया जाता है बनाने

ध्यान दें कि मैंने किसी भी कोड का परीक्षण नहीं किया है और शायद मेरे दृष्टिकोण में कुछ गलतियां हो सकती हैं। हालांकि यह समस्या से निपटने का एक अलग तरीका दिखाता है और शायद आपको एक अच्छा समाधान खोजने में मदद करनी चाहिए।

ध्यान दें कि इस दृष्टिकोण अपलोड को पूरा करने से पहले ही अगले भाग पर ले जाता एक भाग के लिए इंतजार कर रहा है। यदि आपके सर्वर से कनेक्शन अमेज़ॅन से कनेक्शन आपके ब्राउज़र से कनेक्शन से धीमा है, तो यह तंत्र इनपुट धीमा कर देगा।

आप किसी अन्य दृष्टिकोण जहां पूरी करने के लिए भाग अपलोड की Future के लिए इंतजार नहीं है लग सकता है। इसके परिणामस्वरूप एक और चरण होगा जहां आप Future.sequence का उपयोग अपलोड फ्यूचर्स के अनुक्रम को परिणामों में अनुक्रमित करने वाले एक भविष्य में परिवर्तित करने के लिए करेंगे। परिणाम आपके पास पर्याप्त डेटा होने पर अमेज़ॅन के लिए एक हिस्सा भेजना एक तंत्र होगा।

+0

मेरे कोड के साथ हमेशा कई समस्याएं होती हैं। और क्या नया है? लेकिन यह निश्चित रूप से सच है कि सभी मामलों में भाग 5 एमबी नहीं हैं, इसलिए यह एक मुद्दा है। फिर भी, मैं आपके विचारों का प्रयास करूंगा और देख सकता हूं कि मैं क्या कर सकता हूं। – Vidya

संबंधित मुद्दे