7

s3-boto で django-storage を使用する django プロジェクトがあります。

問題は、呼び出しごとに URL が変更されるため、S3 にあるすべてのファイルをキャッシュできないことです。

django-storage によって生成される 2 つの呼び出しを次に示します。

https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg?Signature=HlVSayUIJj6dMyk%2F4KBtFlz0uJs%3D&Expires=1364418058&AWSAccessKeyId=[awsaccesskey]     
https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg?Signature=xh2VxKys0pkq7yHpbJmH000wkwg%3D&Expires=1364418110&AWSAccessKeyId=[awsaccesskey]

ご覧のとおり、署名が異なります。ブラウザのキャッシュが壊れないようにするにはどうすればよいですか?

4

6 に答える 6

10

設定で、次を追加するだけです。

AWS_QUERYSTRING_AUTH = False

これにより、ファイルへの URL が追加のパラメーターなしで生成されることが保証されます。URL は次のようになります。

https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg
于 2013-03-29T20:06:59.377 に答える
6

(デフォルト) の場合AWS_QUERYSTRING_AUTH = True、django はURL を取得するたびに一時的な URLを生成します。

一時的な URL を生成したくない場合:

AWS_QUERYSTRING_AUTH = Falseあなたのsettings.pyに追加してください

それでも一時的な URL が必要な場合:

一時的な URL は秒間有効ですAWS_QUERYSTRING_EXPIRE(デフォルトでは 3600)。したがって、この一時的な URL をキャッシュできます(有効な期間を超えてキャッシュしない限り)。このようにして、後続のページ リクエストに対して同じ URL を返すことができ、クライアント ブラウザがキャッシュからフェッチできるようになります。

設定.py

# We subclass the default storage engine to add some caching
DEFAULT_FILE_STORAGE = 'project.storage.CachedS3Boto3Storage'

プロジェクト/storage.py

import hashlib

from django.conf import settings
from django.core.cache import cache
from storages.backends.s3boto3 import S3Boto3Storage

class CachedS3Boto3Storage(S3Boto3Storage):
    """ adds caching for temporary urls """

    def url(self, name):
        # Add a prefix to avoid conflicts with any other apps
        key = hashlib.md5(f"CachedS3Boto3Storage_{name}".encode()).hexdigest()
        result = cache.get(key)
        if result:
            return result

        # No cached value exists, follow the usual logic
        result = super(CachedS3Boto3Storage, self).url(name)

        # Cache the result for 3/4 of the temp_url's lifetime.
        try:
            timeout = settings.AWS_QUERYSTRING_EXPIRE
        except:
            timeout = 3600
        timeout = int(timeout*.75)
        cache.set(key, result, timeout)

        return result
于 2017-03-20T19:14:16.973 に答える
3

一部のファイル ストレージを保護する

メディア アップロードのほとんど (ユーザー アバターなど) は公開したいと考えています。ただし、アクセスする前に認証が必要なメディアがある場合 (たとえば、メンバーだけがアクセスできる PDF 履歴書など)、S3BotoStorage のデフォルトの S3 ACL である public-read は必要ありません。ここでは、クラスを参照する代わりにインスタンスを渡すことができるため、サブクラス化する必要はありません。

最初に設定のすべてのファイル フィールドの保護を解除し、キャッシュ コントロールを追加します。

AWS_HEADERS = {
    'Cache-Control': 'max-age=86400',
}

# By default don't protect s3 urls and handle that in the model
AWS_QUERYSTRING_AUTH = False

次に、保護する必要があるファイル フィールドを作成して、カスタムの保護されたパスを使用します。

from django.db import models
import storages.backends.s3boto

protected_storage = storages.backends.s3boto.S3BotoStorage(
  acl='private',
  querystring_auth=True,
  querystring_expire=600, # 10 minutes, try to ensure people won't/can't share
)

class Profile(models.Model):
  resume = models.FileField(
    null=True,
    blank=True,
    help_text='PDF resume accessible only to members',
    storage=protected_storage,
  )

ただし、開発中は通常のストレージも使用する必要があり、通常はローカルストレージを使用しているため、これが私が個人的に行った方法です

if settings.DEFAULT_FILE_STORAGE == 'django.core.files.storage.FileSystemStorage':
    protected_storage = FileSystemStorage()
    logger.debug('Using FileSystemStorage for resumes files')
else:
    protected_storage = S3BotoStorage(
        acl='private',
        querystring_auth=True,
        querystring_expire=86400,  # 24Hrs, expiration try to ensure people won't/can't share after 24Hrs
    )
    logger.debug('Using protected S3BotoStorage for resumes files')

参照: https://tartarus.org/james/diary/2013/07/18/fun-with-django-storage-backends

于 2016-07-11T14:24:23.627 に答える
1

最善の策は、Boto S3 Storage Backend をサブクラス化し、url メソッドをオーバーライドすることです。

/project/root/storage.py

from django.conf import settings
from storages.backends.s3boto import S3BotoStorage

class S3Storage(S3BotoStorage):

    def url(self, name):
        name = self._clean_name(name)
        return '{0}{1}'.format(settings.MEDIA_URL, name)

/project/root/settings.py

MEDIA_URL = 'https://my.s3.amazonaws.com/'
DEFAULT_FILE_STORAGE = 'project.storage.S3Storage'
AWS_ACCESS_KEY_ID = '*******'
AWS_SECRET_ACCESS_KEY = '********'
AWS_STORAGE_BUCKET_NAME = 'your-bucket'

画像が公開されていることを確認してください。

于 2013-03-27T20:27:10.170 に答える