Trumbowyg: Django server can detect file upload but not image URL input - javascript

I'm using Trumbowyg, a WYSIWYG JavaScript editor which has a feature of rendering images from URLs pasted in. It also has an upload plugin which enables uploading local images and custom server side handling.
My python/django function upload_image() can successfully detect the uploaded image - however when I use the URL image input, my python function cannot detect it. Trumbowyg simply renders the image without going through my python backend.
Here's my code:
$('#id_content').trumbowyg({
btnsDef: {
// Create a new dropdown
image: {
dropdown: ['insertImage', 'upload'],
ico: 'insertImage'
}
},
// Redefine the button pane
btns: [
['strong', 'em', 'del'],
['link'],
['image'], // Our fresh created dropdown
],
plugins: {
// Add imagur parameters to upload plugin for demo purposes
upload: {
serverPath: '/upload_image/',
fileFieldName: 'content_image',
urlPropertyName: 'url'
}
}
});
def upload_image(request):
print('Success') #only prints when I use the upload input, not the URL input
Why can in detect the uploaded image but not the URL input?

As already pointed, Trumbowyg doesn't send the URL to backend if the user uploads the image using a URL.
But if you really want to host the images on your own server, there's a way you can do that.
When the user submits the form, you'll receive the content of the textarea in your backend. You can then read the content and look for <img src="..."> tag.
At that point, you can check if the src value doesn't start with your S3 bucket hostname, you can download that image using urllib or requests library, save it to your bucket and replace the src value.
Since the submitted data will be in HTML format, check out the excellent Beautiful Soup. It will make parsing HTML easy.

Related

Download pdf with filled data in acroform - PDFJS

I am integrating PDF JS in my web application with enabled renderIntrectiveForm property. So I am able to edit the form input in PDF, I am able to fill inputs. But the problem is I am not able to download the PDF with filled data.
I searched as much as I can. And I tried so hard to achieve the functionality. I also tried to update annotation manually as in below code in download function. But still, it is downloading the original PDF.
var pdf = PDFViewerApplication.pdfDocument;
var downloadManager = PDFViewerApplication.downloadManager;
pdf.loadingTask.then(function(data){
data.getPage(1).then(function(page){
page.getAnnotations().then(function(annotations){
annotations[1].fieldValue= "New Text"
pdf.getData().then(function(blobData){
var blob = (0, PDFJS.createBlob)(blobData, 'application/pdf');
downloadManager.download(blob, "a.pdf", "a.pdf");
})
})
})
});
I know i can send json to server and then create a new pdf with json(as in https://www.smartformsondemand.org). But I want to do it with client side only.

How to upload an image with CKEditor in AngularJS?

Currently I am using angular-ckeditor to add CKEditor 4.
In my template, I display it as:
<div ng-repeat="editor in editors">
<div ckeditor="options" ng-model="editor.content"></div>
</div>
I'm looking for a way to upload images to CKEditor from desktop. As far as I understand, angular-ckeditor and CKEditor libraries are separate, so I can add widgets and plugins easily.
The problem is that I can't seem to find the right plugins/widgets (that do NOT use jQuery), which will help me to upload an image from desktop. I made it work only with image links.
There is not a lot of documentation about it on the official website. They say to use PHP files that will upload and browse images, but don't really explain how, especially with angular-ckeditor. So I have several questions now:
Which plugins do I need for a simple image uploader, so that I can paste images into CKEditor?
How do I set it up with AngularJS?
What does a PHP file uploader(/browser) look like?
What I have tried so far doesn't even change the CKEditor tabs (it should change the image properties dialog by adding an "Upload" tab and some other UI). So clearly I'm missing a solid tutorial somewhere for all of this.
(I could also try to switch to ng-ckeditor, if a solution with this would be simpler)
First, let's take a look at some basics without Angular. For CKEditor version 4, we can initialize an editor with the filebrowserImageUploadUrl configuration option, which enables functionality from the File Browser API:
CKEDITOR.replace('editor', {
filebrowserImageUploadUrl: '/upload.php?type=image'
});
This just loads an editor instance onto a <textarea name="editor">. Because we set the filebrowserImageUploadUrl option, the Upload tab becomes available in the editor's image dialog. The example value, /upload.php?type=image, is the URL to the PHP script on the server that handles the uploaded image files.
When a user uploads an image, CKEditor will send the image to this URL on the server. The handler at this URL should validate the request, resize the image (if needed), and move the uploaded image to a permanent location on the server. Then, the handler sends an HTML response back to CKEditor with the image's public URL.
Of course, we can write the server-side handler in any language. Here's a basic example for PHP that we'll save as upload.php:
<?php
$tempName = $_FILES['upload']['tmp_name'];
$fileName = uniqid() . $_FILES['upload']['name'];
$uploadPath = '/path/to/uploads/' . $fileName;
$imageUrl = 'http://example.com/uploads/' . $fileName;
$success = move_uploaded_file($tempName, $uploadPath);
$html = '<script>window.parent.CKEDITOR.tools.callFunction(%s, "%s", "%s");</script>';
$message = $success ? 'Uploaded successfully.' : 'Upload failed.';
echo sprintf($html, $_GET['CKEditorFuncNum'], $imageUrl, $message);
This script places an uploaded image into the web server's uploads/ directory so the browser can fetch the image. It passes back the CKEditorFuncNum parameter from the request to identify the appropriate callback for the upload. This example provides some basic protection against duplicate filenames, but, for a real-world application, we'd need to add security, validation, and error handling (authentication, CSRF, file type checking, max size, file name sanitization, etc.).
So far, this all works with CKEditor's standard, built-in functionality (no plugins, Angular, or jQuery needed). To enable users to drag-and-drop or paste images into the editor, we can add the Upload Image plugin to our CKEditor build (or use the standard-all distribution from the CKEditor CDN).
We need to declare the plugin when initializing the editor:
CKEDITOR.replace('editor', {
extraPlugins: 'uploadimage',
filebrowserImageUploadUrl: '/upload.php?type=image'
});
...and then extend our upload.php script to return the JSON response expected by the plugin. Add this block before the last three lines of the previous example:
if (isset($_GET['responseType']) && $_GET['responseType'] === 'json') {
echo json_encode([
'uploaded' => $success,
'fileName' => $fileName,
'url' => $imageUrl,
]);
return;
}
The Upload Image plugin sends the responseType=json URL parameter that the server-side script can check for to determine which type of response to send back.
Finally, let's take a look at how to initialize an editor using the angular-ckeditor package described in the question:
<div ng-controller="EditorCtrl as editor">
<textarea ckeditor="editor.options" ng-model="editor.content"></textarea>
</div>
var myApp = angular.module('myApp', ['ckeditor'])
myApp.controller('EditorCtrl', function () {
this.options = {
extraPlugins: 'uploadimage',
filebrowserImageUploadUrl: '/image-upload.php?type=image'
};
});
As we can see, we don't need to do much to "angularize" this. Once we create our template, we declare the same configuration options that we'd pass to the plain CKEDITOR.replace() on a controller that we reference on an element with the ckeditor directive.

Django request.FILES is empty when saving canvas image

I am creating a webapp where the an image is shown to the user and the user can draw on the image (basically the image is in a canvas).
Now once the user is done drawing, the user will press the save button and the image needs to be saved in static folder (not locally). Since I am using Django to accomplish this; my request.FILES is always empty whenever I call the route.
My question is how can I save the canvas on which the user drew to a folder in the project and not locally.
index.html
<div id="uploaderForm">
<form enctype="multipart/form-data" action="{% url 'addImg' %}" method="post">
<input type="hidden" for="image_data" id="image_data" name="image_data" />
</form>
<div class="uploaderItem" id="uploaderSubmit">
Add to the gallery
</div>
</div>
script.js
function addImage()
{
console.log("In add image");
var image_data = canvas.toDataURL();
console.log("Image data:", image_data);
$('#image_data').val(image_data);
$('#uploaderForm > form').submit()
}
views.py
def add(request):
print request.FILES
#print request.POST['image_data']
return HttpResponse("You're looking at question")
the FILES array is reserved for files uploaded in file input fields through a multipart form. What you're doing is passing a base-64 encoded string representing your image, to a hidden text field that is then sent to your server. By your code, the image should be found here:
image_data = request.POST.get('image_data')
It will be a base-64 string, so you'll need to decode it, the example below can be applied to almost any data URL, but the format will depend on your browser, so it's kinda tricky:
import re
pattern = r'^data:(?P<mime_type>[^;]+);base64,(?P<image>.+)$'
result = re.match(pattern, image_data)
if result:
mime_type = result.group('mime_type')
image = result.group('image').decode('base64')
Be careful: by not using a file as transport, you are basically dumping the whole image in the server's memory, and that's expensive if you're planning to serve a lot of clients, and it's also time consuming, so your request could timeout before you are done with the image.
To fix this, you should consider uploading the image through AJAX, which is a supported way to treat Blobs in javascript, that way you could use Django's file upload facilities more efficiently

Customizing CKEditor to work with clear URL in framework

I wrote a small framework with URI structure of lang/domain/controller/method/id an now that I want to use CKFinder integrated with CKEditor I cannot upload and browse server because of address structure? What should I do? To browse the server it uses:
http://localhost/public/admin/style1/plugins/ckfinder/ckfinder.html?CKEditor=abstraction&CKEditorFuncNum=1&langCode=fa
Now I have changed upload and browse address by these:
CKEDITOR.replace('article',
{
filebrowserBrowseUrl : '/browser/browse.php',
filebrowserUploadUrl : '/uploader/upload.php'
});
it shows the images but when I choose them it does not bring it to page and it uploads the file to my image folder but cannot add them or even preview them in body or upload dialogbox. How can I use ckeditor with clear URL?
CKFinder with custom paths
If you are doing URL rewrite and you expect CKFinder to return URLs with custom paths you can do the following:
You can configure how CKFinder sends URLs to CKEditor in CKFinder's config.php file in the backends section:
$config['backends'][] = array(
'name' => 'default',
'adapter' => 'local',
'baseUrl' => 'http://base/url/ckfinder/will/give/to/ckeditor',
'root' => '/path/to/files/on/disk',
'chmodFiles' => 0777,
'chmodFolders' => 0755,
'filesystemEncoding' => 'UTF-8'
);
The file path is appended to all URLs and this behavior can't be changed by configuration.
E.g. for /path/to/files/on/disk/images/picture.png the returned URL is http://base/url/ckfinder/will/give/to/ckeditor/images/picture.png
Alternatively you may add 'useProxyCommand' => true to the backend configuration.
This will change all returned URLs to the form of http://localhost/core/connector/php/connector.php?command=Proxy&lang=en&type=Files&currentFolder=%2F&hash=9fd5e9f22b8dea6a&fileName=picture.png, where http://localhost/core/connector/php/connector.php is the URL that was used to make the request to get the file's URL.
Custom integration with a file manager
If you are implementing your own integration with a file manager check your response from /uploader/upload.php. CKEditor expects something like:
<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction(1, 'http://file/url', 'message');</script>`
You can find more information in the CKEditor's documentation

HTML5: drag out a JS generated file

I have a feeling security concerns may not allow this but is it possible to generate a file with JavaScript and allow the user to drag it to the desktop (or file system)?
The following code drags out a file from a server
files[0].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL", "application/octet-stream:Eadui2.ttf:http://thecssninja.come/demo/gmail_dragout/Eadui.ttf");
},false);
And with the below code I can generate a file and have it download but I can't set the file name or let the user select the location.
var uriContent = "data:application/octet-stream," + encodeURIComponent(JSON.stringify(map));
location.href = uriContent;
Ideally I'd like a magical combination of both.
following code is currently working in Chrome only:
// generate downloadable URL, file name here will not affect stored file
var url = URL.createObjectURL(new File([JSON.stringify(map)], 'file_name.txt'));
// note that any draggable element may be used instead of files[0]
// since JSON.stringify returns a string, we use 'text' type in setData
files[0].addEventListener("dragstart", function(evt) {
evt.dataTransfer.setData("DownloadURL", "text:file_name.txt:" + url);
}, false);
now, dragging our files[0] element from the browser to desktop or file system, will store there a text file called, file_name.txt.
Feel free to choose another file name :)
This is only possible for Chrome, and even in Chrome you can't set the location. If using only Chrome is okay then you will have the following options:
Stick with Drag n' Drop like from the CSS Ninja's tutorial, then you should try Ben's answer. encodeURIComponent is one way, but if you have the file generated using BlobBuilder then you can use window.webkitURL.createObjectURL() to get the file's URL. You can also try using FileWriter() with requestFileSystem(TEMPORARY, ...).
Chrome supports download attribute for anchor tags so you can have regular link for the user to click (dragging also works):
Download
For cross browser support I suggest Downloadify.
You could try sending it to the server, saving the file, checking the return value and firing the download file function, followed by a server file that deletes the file from the server.
Something like this (with jQuery)
$.ajax({
url: 'saveFile.php',
method: 'post',
data: {
Filedata: data// file data variable
},
success: function(d) {
// save file function, where d is the filename
}
})
PHP:
$filename = ;//generate filename
file_put_contents($filename, $_POST['Filedata']);
echo $filename;
Obviously there is more to it but that should be the basics

Categories