0

我在 Django 中创建了一个图像共享网站,我将缩略图文件保存在服务器上,将原始文件保存在对象存储中。我能够上传图像(对象存储上的原始图像和服务器上的缩略图)。但是,问题是我无法从对象存储中下载图像。

有什么方法可以从对象存储中下载图像。

这是我的代码。

我的 settings.py :

    # Static files (CSS, JavaScript, Images)
   # https://docs.djangoproject.com/en/3.1/howto/static-files/

   AWS_ACCESS_KEY_ID = 'xxx'
   AWS_SECRET_ACCESS_KEY = 'xxx'
   AWS_STORAGE_BUCKET_NAME = 'my-bucket-name'
   AWS_S3_ENDPOINT_URL = 'endpoint-url'
   AWS_S3_CUSTOM_DOMAIN = 'my-custom-domain-name'
   AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=31536000',
   }

   AWS_DEFAULT_ACL = 'public-read'

   #DEFAULT_FILE_STORAGE = "custom_storages.MediaStorage" (Commented Code) 

   MEDIA_URL = BASE_DIR / 'media'
   MEDIA_ROOT = 'media/'

模型.py

from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFit
from django.urls import reverse
import os
from django.conf import settings
from custom_storages import MediaStorage

class Image(models.Model):
def get_image_path(instance, filename):
    return os.path.join('images', str(instance.subcategory.category.category_name), str(instance.subcategory.sub_name), filename)

image = models.ImageField(upload_to=get_image_path, storage=MediaStorage(), null=True) #Here I'm saving my image to object storage using custom storage class
image_thumbnail = ImageSpecField(source='image', processors=[ResizeToFit(480,480)], format='JPEG', options={'quality':60}) #generating thumbnail using django-imagekit

custom_storages.py - 使用它来将我的文件存储在对象存储中

import os
from storages.backends.s3boto3 import S3Boto3Storage
from tempfile import SpooledTemporaryFile

class MediaStorage(S3Boto3Storage):
    bucket_name = 'my-bucket-name'
    location = 'media'

def _save(self, name, content):
    """
    We create a clone of the content file as when this is passed to
    boto3 it wrongly closes the file upon upload where as the storage
    backend expects it to still be open
    """
    # Seek our content back to the start
    content.seek(0, os.SEEK_SET)

    # Create a temporary file that will write to disk after a specified
    # size. This file will be automatically deleted when closed by
    # boto3 or after exiting the `with` statement if the boto3 is fixed
    with SpooledTemporaryFile() as content_autoclose:

        # Write our original content into our copy that will be closed by boto3
        content_autoclose.write(content.read())

        # Upload the object which will auto close the
        # content_autoclose instance
        return super(MediaStorage, self)._save(name, content_autoclose)

views.py - 单击下载按钮时,调用此函数

def download(request,id):
previous_url = request.META.get('HTTP_REFERER')
if request.method == 'POST':
    recaptcha_response = request.POST.get('g-recaptcha-response')
    data = {
        'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
        'response': recaptcha_response
    }
    r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data)
    result = r.json()
    ''' '''End reCAPTCHA validation''' '''

    if result['success']:
        image = Image.objects.get(id=id)
        file_name = os.path.basename(image.image.name)
        file_path = image.image.name
        fl = storage.open(file_path, "rb")
        print(fl)
        content_type = mimetypes.guess_type(file_path)[0]
        response = HttpResponse(fl, content_type=content_type)
        response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
        response['X-Sendfile'] = smart_str(file_path)
        return response
    else:
        messages.error(request, 'Invalid reCAPTCHA. Please try again.')
        return redirect(previous_url)
else:
    return redirect(previous_url)

调用下载函数时,显示错误,因为 media_root 设置为服务器位置。有没有可能使用 DEFAULT_FILE_STORAGE 和 MEDIA_ROOT 来下载对象存储中的图像。或者我如何修改我的下载代码,以便它从对象存储中下载图像。任何帮助表示赞赏。谢谢!

4

0 回答 0