Почему в контейнере aws s3 отображается неверный тип параметра? - PullRequest
0 голосов
/ 28 сентября 2019

Я пытаюсь загрузить изображение в корзину s3, но оно показывает следующую ошибку.Я использую React и DRF.

Я следую этому учебнику .Там они предложили создать подписанный URL-адрес из бэкэнда, а затем с помощью подписанного URL-адреса отреагировать на запрос сервера s3 загрузить изображение.

Traceback:

File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/app/.heroku/python/lib/python3.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/app/.heroku/python/lib/python3.7/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/app/.heroku/python/lib/python3.7/site-packages/rest_framework/views.py" in dispatch
  497.             response = self.handle_exception(exc)

File "/app/.heroku/python/lib/python3.7/site-packages/rest_framework/views.py" in handle_exception
  457.             self.raise_uncaught_exception(exc)

File "/app/.heroku/python/lib/python3.7/site-packages/rest_framework/views.py" in raise_uncaught_exception
  468.         raise exc

File "/app/.heroku/python/lib/python3.7/site-packages/rest_framework/views.py" in dispatch
  494.             response = handler(request, *args, **kwargs)

File "/app/articles/api/views.py" in get
  82.             ExpiresIn=3600

File "/app/.heroku/python/lib/python3.7/site-packages/botocore/signers.py" in generate_presigned_post
  688.         {'Bucket': bucket}, operation_model)

File "/app/.heroku/python/lib/python3.7/site-packages/botocore/validate.py" in serialize_to_request
  297.                 raise ParamValidationError(report=report.generate_report())

Exception Type: ParamValidationError at /api/blog/api/create-permission/aws-s3/
Exception Value: Parameter validation failed:
Invalid type for parameter Bucket, value: None, type: <class 'NoneType'>, valid types: <class 'str'>
Request information:
USER: XXXder

GET:
image_name = 'asd_adasd_thumb.jpg'

POST: No POST data

FILES: No FILES data

settings.py

AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_REGION_NAME = 'ap-south-1'
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}

Как я сгенерировал signature_url

import os
import datetime
import boto3
import mimetypes


s3 = boto3.client('s3', config=Config(signature_version='s3v4'))


class SignS3Upload(APIView):
    # authentication_classes = (authentication.SessionAuthentication,)
    # permission_classes = [IsAuthenticated, ]

    def get(self, request):
        s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')
        file_name = request.GET['image_name']
        file_type = mimetypes.guess_type(file_name)[0]
        presigned_post = s3.generate_presigned_post(

            Bucket=s3_bucket,
            Key=file_name,
            Fields={"acl": "public-read", "Content-Type": file_type},
            Conditions=[
                {"acl": "public-read"},
                {"Content-Type": file_type},
                {"x-amz-algorithm": "AWS4-HMAC-SHA256"}

            ],
            ExpiresIn=3600
        )

        data = {
            "signed_url": presigned_post,
            'url': 'https://%s.s3.amazonaws.com/%s' % (s3_bucket, file_name)
        }
        return Response(data)

Во внешнем интерфейсе я использую React с Redux.

export const getSignedRequest = (image) => (dispatch, getState) => {


    const image_name = image.name
    const type = image.type

    axios.get('https://abc-abc.herokuapp.com/api/blog/api/create-permission/aws-s3/', { params: { image_name } })
        .then((res) => {
            dispatch({
                type: GET_PARTICULAR_BLOG_IMG_UPLOAD,
                payload: res.data
            });

            var postData = new FormData();
            var key
            for (key in res.data.signed_url.fields) {

                postData.append(key, res.data.signed_url.fields[key]);
            }
            postData.append('file', image);

            ////////// Here I'm sending request to s3//////////////////////

            return axios.post(res.data.signed_url.url, postData);
        })
        .then((res) => {
            dispatch({
                type: GET_PARTICULAR_BLOG_IMG_UPLOAD_AWS,
                payload: res.data
            });
        })
        .catch(err => {
            //dispatch(returnErrors(err.response.data, err.response.status));
            console.log(err)
            dispatch({
                type: GET_PARTICULAR_BLOG_IMG_UPLOAD_FAIL
            });
        });

};

Вот форма

    fileSelectHandler = event => {

        const files = document.getElementById("file_input").files;
        const file = files[0]

        if (!file) {
            return alert("Please select Image")
        }

        this.props.getSignedRequest(file)

    }


 <Form onSubmit={this.handleSubmit} className='blog_form' encType="multipart/form-data" method='POST'>

<input className="upload" type="file" accept='image/*' name='image' onChange={this.fileSelectHandler} id="file_input" />
<Button type="primary" htmlType='submit' className="BlogButton">Create Blog</Button>
</Form>

РЕДАКТИРОВАНИЕ:

Когда я пробовал это с localhost, кажется, что он генерирует подписанный URL Пожалуйста, проверьте этот скриншот

Но статус ответа (от s3) - 204 Пожалуйста, проверьте эти изображения

Работает нормально с localhost, загружая изображение на s3.Но не тогда, когда я развернул его на героку.При попытке от Heroku я получаю ту же ошибку, упомянутую сверху.

1 Ответ

0 голосов
/ 29 сентября 2019

Как указано в ошибке, значение, переданное параметру Bucket, равно 'None', что является недопустимым значением.

Exception Value: Parameter validation failed:
Invalid type for parameter Bucket, value: None, type: <class 'NoneType'>, valid types: <class 'str'>

Вы читаете имя корзины из системной среды

s3_bucket = os.environ.get('AWS_STORAGE_BUCKET_NAME')

, который не может быть установлен в среде heroku.

Функция os.environ.get возвращает None, если ключ отсутствует в среде.

...