Python zappa任务用于将文件上传到S3存储桶。

huangapple go评论70阅读模式
英文:

Python zappa task for uploading files to S3 bucket

问题

我尝试将上传照片的功能移到Zappa任务中。

views.py

  1. def perform_create(self, serializer):
  2. photos = dict((self.request.data).lists())['photos']
  3. for photo in photos:
  4. byte = base64.b64encode(photo.read())
  5. upload_photos(byte.decode('utf-8'), photo.name)

tasks.py

  1. @task
  2. def upload_photos(photo, name):
  3. byte_data = photo.encode(encoding='utf-8')
  4. b = base64.b64decode(byte_data)
  5. img = Image.open(io.BytesIO(b))
  6. width = img.width
  7. height = img.height
  8. with open(name, 'rb') as file:
  9. picture = File(file)
  10. Images.objects.create(photo=picture, width=width, height=height)
  11. os.remove(name)

在本地一切正常,照片上传到S3存储桶。但是当我部署到AWS上时,我在img.save()上遇到了错误:

  1. oserror: [Errno 30] Read-only file system: 'file-name.jpg'

据我所知,问题出在临时将文件保存在内存中。也许我需要指定临时路径?有什么办法可以修复吗?

英文:

I've tried to move upload photos functional to zappa task.
views.py

  1. def perform_create(self, serializer):
  2. photos = dict((self.request.data).lists())['photos']
  3. for photo in photos:
  4. byte = base64.b64encode(photo.read())
  5. upload_photos(byte.decode('utf-8'), photo.name)

tasks.py

  1. @task
  2. def upload_photos(photo, name):
  3. byte_data = photo.encode(encoding='utf-8')
  4. b = base64.b64decode(byte_data)
  5. img = Image.open(io.BytesIO(b))
  6. width = img.width
  7. height = img.height
  8. with open(name, 'rb') as file:
  9. picture = File(file)
  10. Images.objects.create(photo=picture, width=width, height=height)
  11. os.remove(name)

Locally everything works fine, photos uploaded to S3 bucket. But when I deployed zappa to AWS I've got the error on img.save():

  1. oserror: [Errno 30] Read-only file system: 'file-name.jpg'

As I understand, the problem with temporarily saving file in memory. Maybe I have to specify tmp path?
Any ideas how can I fix it?

答案1

得分: 0

这是我的解决方案,它在使用zappa+S3和本地环境时都能完美运行。您也可以在序列化器的创建方法中使用这个逻辑:

views.py

  1. from django.core.files.base import ContentFile
  2. from django.core.files.storage import default_storage
  3. def perform_create(self, serializer):
  4. photos = dict((self.request.data).lists())['photos']
  5. for photo in photos:
  6. path = default_storage.save(f'tmp/{photo.name}', ContentFile(photo.read()))
  7. return s3_upload_photo(path, photo.name)

tasks.py

  1. @task()
  2. def s3_upload_photo(path, file_name):
  3. path_object = Path(path)
  4. with default_storage.open('tmp/' + file_name, 'rb') as file:
  5. photo = File(file, name=path_object.name)
  6. width, height = get_image_dimensions(photo)
  7. instance = ModelName.objects.create(photo=photo, width=width, height=height)
  8. default_storage.delete(path)
  9. return instance
英文:

Here is my solutions, it perfectly works with zappa+S3 and locally. You can use this logic in serializer create method also:
views.py

  1. from django.core.files.base import ContentFile
  2. from django.core.files.storage import default_storage
  3. def perform_create(self, serializer):
  4. photos = dict((self.request.data).lists())['photos']
  5. for photo in photos:
  6. path = default_storage.save(f'tmp/{photo.name}', ContentFile(photo.read()))
  7. return s3_upload_photo(path, photo.name)

tasks.py

  1. @task()
  2. def s3_upload_photo(path, file_name):
  3. path_object = Path(path)
  4. with default_storage.open('tmp/' + file_name, 'rb') as file:
  5. photo = File(file, name=path_object.name)
  6. width, height = get_image_dimensions(photo)
  7. instance = ModelName.objects.create(photo=photo, width=width, height=height)
  8. default_storage.delete(path)
  9. return instance

huangapple
  • 本文由 发表于 2023年6月19日 23:06:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507895.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定