我正在开发一个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'})
1条答案
按热度按时间syqv5f0l1#
我被困在这一整天,现在的解决方案看起来很简单。只是创建一个普通的url,没有预先签名的元素。