2016-06-09 4 views
11

मैं एस 3 से एक फ़ाइल डाउनलोड करने की कोशिश कर रहा हूं और उस फ़ाइल को एस 3 में दूसरी बाल्टी में अपलोड कर रहा हूं। कॉपी एपीआई यहां काम नहीं करेगी क्योंकि मुझे बताया गया है कि इसका इस्तेमाल न करें।मैं io.ReadCloser से io.ReadSeeker पर कैसे जा सकता हूं?

S3 से एक वस्तु हो रही एक response.Body कि एक io.ReadCloser है और उस फ़ाइल को अपलोड करने के लिए पेलोड एक Body कि एक io.ReadSeeker है लेता है।

एकमात्र तरीका जिसे मैं समझ सकता हूं, response.Body को फ़ाइल में सहेजकर io.ReadSeeker के रूप में फ़ाइल को पास कर रहा है। इसके लिए पूरी फ़ाइल को डिस्क पर पहले लिखने की आवश्यकता होगी, फिर पूरी फ़ाइल को डिस्क से पढ़ना होगा जो बहुत गलत लगता है।

मुझे क्या करना चाहते हैं:

resp, _ := conn.GetObject(&s3.GetObjectInput{Key: "bla"}) 
conn.PutObject(&s3.PutObjectInput{Body: resp.Body}) // resp.Body is an io.ReadCloser and the field type expects an io.ReadSeeker 

प्रश्न है, मैं कैसे संभव सबसे कारगर तरीका में एक io.ReadSeeker के लिए एक io.ReadCloser से जाते हैं?

+0

आप किस विशिष्ट API और फ़ंक्शंस का उपयोग कर रहे हैं? मुझे उन कार्यों को नहीं मिल रहा है जिन्हें आप गो एस 3 एसडीके में संदर्भित कर रहे हैं। https://docs.aws.amazon.com/sdk-for-go/api/service/s3.html – BadZen

+0

@ बैडज़ेन मैंने उन कॉल को जोड़ दिया है जिनका मैं उपयोग करूँगा। – Jeff

+0

यह अजीब बात है कि आप प्रतिलिपि कार्यों का उपयोग नहीं कर सकते हैं - यही वह है जो वे वहां हैं। शायद उस पर वापस धक्का। डिस्क पर फ़ाइल लिखने के अलावा आपका एकमात्र अन्य विकल्प आपके 'io.ReadSeeker' अनुरोध अनुरोध पर GetObject() को फिर से जारी करने जा रहा है, और खोज की स्थिति से शुरू करने के लिए श्रेणी फ़ील्ड सेट कर रहा है। हालांकि, यह पहले से ही गलत लिखने-से-डिस्क की तुलना में एक खराब समाधान है। – BadZen

उत्तर

7

io.ReadSeeker वह इंटरफ़ेस है जो मूल Read() और Seek() विधियों को समूहित करता है। Seek() विधि की परिभाषा:

Seek(offset int64, whence int) (int64, error) 

Seek() विधि का एक कार्यान्वयन कहीं भी स्रोत है, जो सभी स्रोत की आवश्यकता उपलब्ध या प्रतिलिपि प्रस्तुत करने योग्य होने के लिए तलाश करने के लिए सक्षम होने के लिए की आवश्यकता है। एक फ़ाइल एक आदर्श उदाहरण है, फ़ाइल को आपकी डिस्क पर स्थायी रूप से सहेजा जाता है और इसके किसी भी हिस्से को किसी भी समय पढ़ा जा सकता है।

response.Body अंतर्निहित टीसीपी कनेक्शन से पढ़ने के लिए लागू किया गया है। अंतर्निहित टीसीपी कनेक्शन से पढ़ना आपको वह डेटा देता है जो दूसरी तरफ ग्राहक आपको भेजता है। डेटा कैश नहीं किया गया है, और क्लाइंट आपको अनुरोध पर फिर से डेटा नहीं भेजेगा। यही कारण है कि response.Bodyio.Seeker लागू नहीं करता है (और इस प्रकार io.ReadSeeker या तो)।

तो आदेश में एक io.Reader या io.ReadCloser से एक io.ReadSeeker प्राप्त करने के लिए, आप कुछ है कि सभी डेटा कैश, ताकि अनुरोध पर यह है कि में कहीं भी प्राप्त कर सकते हैं की जरूरत है।

यह कैशिंग तंत्र एक फ़ाइल में लेखन किया जा सकता है के रूप में आप का उल्लेख किया है, या आप स्मृति में सब कुछ पढ़ सकते हैं एक []byteioutil.ReadAll() का उपयोग करते हुए, और फिर आप bytes.NewReader() का प्रयोग कर एक []byte से एक io.ReadSeeker प्राप्त करने के लिए कर सकते हैं। बेशक इसकी इसकी सीमाएं हैं: सभी सामग्री को स्मृति में फिट होना चाहिए, और हो सकता है कि आप इस फ़ाइल कॉपी ऑपरेशन के लिए उस स्मृति की मात्रा को आरक्षित नहीं करना चाहें।

कुल मिलाकर, io.Seeker या io.ReadSeeker के एक कार्यान्वयन उपलब्ध होने की सभी स्रोत डेटा की आवश्यकता है, तो आपका सर्वश्रेष्ठ दांव एक []byte में एक फ़ाइल में लिख रहा है, या के लिए सभी को पढ़ने के छोटे फ़ाइलों और कहा कि बाइट की सामग्री की स्ट्रीमिंग टुकड़ा।

8

वैकल्पिक रूप से, github.com/aws/aws-sdk-go/service/s3/s3manager.Uploader का उपयोग करें, जो io.Reader इनपुट के रूप में उपयोग करता है।

मैं कारण की कल्पना PutObject लेता है कि एक io.Reader के बजाय एक io.ReadSeeker कि S3 के लिए अनुरोध पर हस्ताक्षर किया जाना (और एक सामग्री की लंबाई है) की जरूरत है, लेकिन आप एक हस्ताक्षर उत्पन्न नहीं कर सकते जब तक आप सभी डेटा है। ऐसा करने के लिए स्ट्रीम-वाई तरीका भाग में इनपुट को बफर करना होगा और प्रत्येक खंड को अलग से अपलोड करने के लिए मल्टीपार्ट अपलोडिंग एपीआई का उपयोग करना होगा। यह है (मुझे लगता है) दृश्यों के पीछे s3manager.Uploader क्या करता है।

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