Open gurugeek opened 3 years ago
I have the same problem, please solve it
@mr-nazari feel free to provide a patch I will make the release.
Can anyone help me with how to insert a local image?
You need to write the JS uploader and then the Django view to handle the upload yourself. Here's what I did to achieve this where I use Django Storages as the backend but I use default_storage to write the file to the backend so everything should work for you with the exception of the full URL to the uploaded file.
Step 1. Ensure the the these two keys are set within the TINYMCE_DEFAULT_CONFIG
"images_upload_url": "/tinymce/upload",
"images_upload_handler": "tinymce_image_upload_handler"
The first is the path to which you would like the javascript to make the POST. The 2nd is the name of the javascript function to handle the upload
Step 2 Because of CSRF you need to be able to read the token. In order to do this I use the js-cookie lib mentioned within the Django docs
Add the below into your settings.py to tell it yo include two additional JS file. I'm using the jsdelivr CDN hosted version for the above package
TINYMCE_EXTRA_MEDIA = {
'css': {
'all': [
],
},
'js': [
"https://cdn.jsdelivr.net/npm/js-cookie@3.0.1/dist/js.cookie.min.js",
"admin/js/tinymce-upload.js",
],
}
The second file is holds the custom JS file upload handler I will post below.
Step 3. Here are the contents of the tinymce-upload.js file I created. Note it uses cookie-js to read the value of the CSRF token and add it to the headers of the AJAX POST. I also hardset the URL path to post to as the same value as the one I add in the settings.py. You may be able to read it from somewhere but I haven't looked into that yet.
function tinymce_image_upload_handler (blobInfo, success, failure, progress) {
let xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/tinymce/upload');
xhr.setRequestHeader('X-CSRFToken', Cookies.get("csrftoken"));
xhr.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
xhr.onload = function() {
let json;
if (xhr.status === 403) {
failure('HTTP Error: ' + xhr.status, { remove: true });
return;
}
if (xhr.status < 200 || xhr.status >= 300) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
xhr.onerror = function () {
failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
}
Step 4 Write the view to handle the upload. In my case I want to use a subfolder of media called tinymce with a uuid4 named folder to then hold the file in to avoid name clashes.
The key part is to return a JSONResponse with the location of the image you just uploaded.
In my case I am using Django Storages to store files on S3 but I serve them from AWS Cloudfront using a custom domain that I have set within settings.py so I append that to the start
def tinymce_upload(request):
"""Uplaod file to S3 and return the location"""
file = request.FILES.get('file')
filename = f"tinymce/{uuid4()}/{str(file)}"
with default_storage.open(filename, "wb") as f:
f.write(file.read())
return JsonResponse({"location": f"https://{settings.AWS_S3_CUSTOM_DOMAIN}/media/{filename}"})
Now I can upload images using the TinvMCE plugin ensuring that CSRF checks are made
Thanks for your package :)
Drag and Drop images using the paste plugin doesn't seem to work:
returns "dropped file top not supported". It works fine in the plain JS version so I was wondering if this is disabled on Django ?
I would appreciate any assistance on how to use drag and drop images OR add images easily. Thanks!