2016-02-22 43 views
1

試圖上傳文件到S3具有:Boto3 S3:類型錯誤:脅迫爲Unicode:需要字符串或緩衝區,文件中發現

# boto3 s3 client 
    s3.put_object(Bucket=self.bucket, 
        Body=open(upload_file, 'rb'), 
        Key=k.key, 
        SSECustomerAlgorithm='AES256', 
        SSECustomerKey=base64.b64encode(data_key), 
        SSECustomerKeyMD5=base64.b64encode(data_key_md5) 
       ) 

,並在此行得到了錯誤:

TypeError: coercing to Unicode: need string or buffer, file found 

upload_file變量<type 'file'>dir

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines'] 

切換到open(upload_file, 'rb').read()不會幫助。另外我的文件可能很大(如此1GB),將它們保存爲字符串是不合理的。

我知道它會工作,如果我將upload_file設置爲文件路徑,但我沒有這個文件在磁盤上,它通過表單提交。

UPDATE

它的怪異,但是當我使用的測試文件或字符串(測試的緣故)得到了類似的問題:

TypeError: expected string or buffer

這是響應爲:

# boto3 s3 client 
s3.put_object(Bucket=self.bucket, 
    # put existing filr 
    Body=open('/tml/existing-file', 'rb'), # adding read() wont help 
    # ... 
) 

相同的字符串:

# boto3 s3 client 
s3.put_object(Bucket=self.bucket, 
    # put existing filr 
    Body='some random string', 
    # ... 
) 
+0

當你設置'Body = open(upload_file,'rb')。read()'?時,你會得到什麼錯誤? – wpercy

+0

@wilbur '*** TypeError:強制轉換爲Unicode:需要字符串或緩衝區,找到文件'此文件來自窗體,'<打開文件'',模式'w + b'*** **** –

+0

如果只是將'upload_file'傳遞給'Body'而不是試圖打開它呢? – wpercy

回答

0

不知道爲什麼我不能使它與boto3一起工作,但在這裏工作代碼與以前,boto2版本。唯一的區別是:你需要在頭部添加放參數,根據官方文檔: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html 在我的代碼情況下的樣品,其木材的樣子:

headers.update({ 
     'x-amz-server-side-encryption-customer-algorithm': 'AES256', 
     'x-amz-server-side-encryption-customer-key': base64.b64encode(data_key), 
     'x-amz-server-side-encryption-customer-key-MD5': base64.b64encode(data_key_md5) 
    }) 

    k.set_contents_from_file(upload_file, headers=headers) 

正如你看到的upload_file做工精細,在這種情況下, 。

0

我建議您將輸入流寫入臨時文件並使用Bucket.upload_file傳輸文件。在Web服務應用程序中將大文件保存在內存中並不好。考慮你有多個併發上傳請求,這會佔用大量的內存。

import tempfile 
import shutil 
file_ = file_like_object_from_form_submit 
with tempfile.NamedTemporaryFile() as tmpfile: 
    shutil.copyfileobj(file_, tmpfile) 
    tmpfile.flush() 
    self.bucket.upload_file(tmpfile.name, path) 
+0

試圖避免這一點..但會嘗試並給你反饋 –

+0

只有一半是真實的。類文件對象是'put_object'的有效主體,但不適用於'upload_file' –

+0

@ jordon-phillips你有更好的主意嗎? –

相關問題