django Tinymce不会为上传的图片生成预签名的url

q9rjltbz  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(144)

我正在开发一个Django博客应用程序,我使用Tinymce作为文章内容的文本编辑器。为了存储上传的图像,我使用AWS S3。问题是Tinymce不会为上传的图片生成预签名的URL,导致到达到期时间时出现拒绝访问错误。
这是我得到的错误:
AccessDenied请求已过期3600 2023-06- 07 T03:26:09 Z 2023-06- 07 T15:46:49 Z xxxxxxxxx xxxxxxx
当通过Tinymce上传图像时,它会作为链接存储在文本区域中。然而,Tinymce在打开帖子时不会为图像生成新的预签名URL,导致图像保留在帖子保存操作期间最初生成的URL。
由于Tinymce图像的预签名URL不会更改,因此当达到为URL设置的过期时间时,图像变得不可访问,并且我遇到“访问拒绝”错误。
我在博客上有其他图片,服务很好。问题只是发生在那些上传到Tinymce
下面是一些相关的代码片段:
uploadfile.js

const image_upload_handler_callback = (blobInfo, success, failure, progress) => {
    const xhr = new XMLHttpRequest();
    xhr.withCredentials = false;
    xhr.open('POST', '/' + userLanguage + '/upload_image/');

    xhr.upload.onprogress = (e) => {
        progress(e.loaded / e.total * 100);
    };
    
    xhr.onload = () => {
        if (xhr.status === 403) {
            failure('HTTP Error: ' + xhr.status);
            return;
        }
      
        if (xhr.status < 200 || xhr.status >= 300) {
            failure('HTTP Error: ' + xhr.status);
            return;
        }
      
        const json = JSON.parse(xhr.responseText);
      
        if (!json || typeof json.file_path != 'string') {
            failure('Invalid JSON: ' + xhr.responseText);
            return;
        }
      
        success(json.file_path);
    };
    
    xhr.onerror = () => {
      failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
    };
    
    const formData = new FormData();
    const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    formData.append('csrfmiddlewaretoken', csrftoken); // Add CSRF token to form data
    formData.append('image', blobInfo.blob(), blobInfo.filename());
    
    xhr.send(formData);
};

tinymce.init({
    selector: 'textarea',
    plugins: 'image textcolor',
    toolbar: 'undo redo | bold italic | alignleft aligncenter alignright alignjustify | image',
    images_upload_handler: image_upload_handler_callback,
});

settings.py

# AWS
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')

AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
AWS_S3_REGION_NAME = 'us-east-1'
AWS_S3_SIGNATURE_VERSION = 's3v4'
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

THUMBNAIL_DEFAULT_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

CORS_ALLOW_ALL_ORIGINS = True

views.py

class TinymceS3Storage(S3Boto3Storage):
    location = 'media/uploads/tinymce/images'
    file_overwrite = False  # Optional: Set to True if you want to overwrite existing files

    def get_default_headers(self, *args, **kwargs):
        headers = super().get_default_headers(*args, **kwargs)
        headers['Cache-Control'] = 'public, max-age=31536000'
        return headers

def upload_image(request):
    if request.method == 'POST':
        image = request.FILES.get('image')

        # Generate a unique filename for the image
        filename = f"{uuid.uuid4().hex}{image.name.split('.')[-1]}"

        # Save the image to S3
        storage = TinymceS3Storage()
        image_path = storage.save(filename, image)

        # Construct the public URL for the uploaded image
        image_url = storage.url(image_path)

        # Return the image URL as a JSON response
        return JsonResponse({'file_path': image_url})

    else:
        return JsonResponse({'error': 'Invalid request method'})
syqv5f0l

syqv5f0l1#

我被困在这一整天,现在的解决方案看起来很简单。只是创建一个普通的url,没有预先签名的元素。

image_url = f"https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{image_path}"

相关问题