3

編集:私はこの問題を解決し、下に答えを出しました。

django-storages を使用して、 SFTP を使用して「Hetzner」ストレージ ボックス ( https://www.hetzner.com/storage/storage-box )にアクセスしようとしています。これには、メディア データ、つまり、私の Web サイトのユーザーが使用できる画像ファイルを保持する必要があります。動的にアップロードします。

ファイルの対応する部分はsettings.py次のようになります。

DEFAULT_FILE_STORAGE = 'storages.backends.sftpstorage.SFTPStorage'
SFTP_STORAGE_HOST = 'username.your-storagebox.de'
SFTP_STORAGE_ROOT = '/media'

SFTP_STORAGE_PARAMS = {
'username': 'username',
'password': 'password',
'allow_agent': False,
'look_for_keys': False,
}

奇妙なことに、ユーザーがイメージをアップロードすると、SFTP を使用して確認できるように、ストレージ スペースに配置されます。しかし、ストレージ ボックスからの画像の取得に失敗し、画像が表示されません。コンソールからの抜粋:

[03/Sep/2021 22:34:01] "GET /media/filename.jpg HTTP/1.1" 404 1962

Django がまだMEDIA_DIRファイルを探していることがわかりました。繰り返しますが、私の設定の対応する部分:

MEDIA_DIR = 'media'
MEDIA_ROOT = os.path.join(BASE_DIR, MEDIA_DIR)
MEDIA_URL = '/media/'

一言で言えば、SFTP を使用すると、ファイルをストレージに入れるのに機能しているように見えますが、ファイルを再度取得することはどういうわけか失敗します。

私はいくつかの助けを望んでいます。前もって感謝します!

編集: 要求に応じて、さらにいくつかのコード スニペットを提供します: models.py:

class SizeRestrictedImageField(ImageField):

    def __init__(self, *args, **kwargs):
        self.max_upload_size = kwargs.pop('max_upload_size', 0)
        super().__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        data = super().clean(*args, **kwargs)

        file = data.file
        try:
            if file.size > self.max_upload_size:
                raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s'
                        ) % (filesizeformat(self.max_upload_size),
                        filesizeformat(file.size)))
        except AttributeError:
            logger.exception('An Exception occured while checking for max size of image upload. size: `%s`'
                             , file.size)
            pass

        return data


class ImageModel(models.Model):
    image = SizeRestrictedImageField(upload_to=POST_PIC_FOLDER, null=True, blank=True,
                              help_text="Erlaubte Dateitypen: .jpeg, .jpg, .png, .gif", max_upload_size=MAX_IMAGE_SIZE)

そして私のurls.py

urlpatterns = [
                  path('defaultsite/', defaultsite_view, name='home'),
                  path('help', help_view, name="help"),
                  path('user/', include('user.urls')),
                  path('sowi/', include('sowi.urls')),
                  path('blog/', include('blog.urls')),
                  path('chat/', include('chat.urls')),
                  path('notifications/', include('notifications.urls')),
                  path('cookies/', include('cookie_consent.urls')),
                  path('', home_view, name="home"),
                  path('about/', AboutUsView.as_view(), name="about-us"),
                  path('impressum/', impressum_view, name="imprint"),
                  path('privacy/', privacy_view, name='privacy'),
                  path('privacy/statement/', privacy_statement_view, name='privacy-statement'),
                  path('agb', agb_view, name="agb")
              ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL,
                                                                                           document_root=settings.MEDIA_ROOT)

+static(...)url-patterns から -part を削除しようとしましたが、問題は解決していないようです。

4

2 に答える 2

1

django-storage のセットアップを確認する

django モデルでフィールドを移行するのを忘れたのではないでしょうか? django-storage Github のドキュメントには、これらのコードのスニペットがあります。

から:

photo = models.FileField(
    storage=FileSystemStorage(location=settings.MEDIA_ROOT),
    upload_to='photos',
)

に:

photo = models.FileField(
    upload_to='photos',
)

あれでしょうか?(コメントで言及されているように、コードのスニペットがあれば非常に役立ちます。

SFTP アクセス

Django-storageact には、ファイルをどこかに保存するためのプロキシがあります。私は s3 バケット、http cdn のようなものになることができます。または、あなたの場合はSFTPサーバーです。

HTTP プロトコルをサポートする他のバックエンドでは、ファイルを取り戻すのはかなり簡単です。バックエンドは、保存したコンテンツへのリンクを直接提供します。

SFTP の場合、これは異なります。Web ページは FTP プロトコルをネイティブにサポートしていません。したがって、ファイルにアクセスするには、Web ページと FTP サーバーの間にプロキシ層を作成する必要があります。

@action(methods=['get'], detail=True)
def download(self, request, pk=None):

    try:
        obj = ImageModel.objects.get(id=pk)
    except ImageModel.DoesNotExist:
        raise Http404

    # with some SFTP client
    # 1. check the file exist
    # 2. pull the file from the server
    # 3. attach it to the response with the proper header
    stream = sftp_client.open(obj.file.name)
    file = stream.read()

    type, encoding = mimetypes.guess_type(obj.file.name)
    response = HttpResponse(file, content_type=type)
    response['Content-Disposition'] = u'attachment; filename="{filename}'.format(
            filename=obj.file.name)
        return response
    raise Http404
于 2021-09-05T21:08:34.623 に答える