Can anyone tell me how to upload image in summernote editor (angularJs v.)?
My Code:
$scope.imageUpload = function(files) {
uploadEditorImage(files);
};
function uploadEditorImage(files) {
if (files != null) {
Upload.upload({
url: ROUTES.RESOURCESUPLOADFILE,
file: files
}).success(function(data, status, headers, config) {
var uploaded_file_name = data.file_name,
file_location = '/assets/uploads/'+uploaded_file_name;
$scope.editor.summernote('editor.insertImage', uploaded_file_name);
});
}
};
<summernote editor="editor" editable="editable" on-image-upload="imageUpload(files)" ng-model="lessonFormEditData.description" ></summernote>
Error:
TypeError: Cannot read property 'summernote' of undefined
Also "editable" parameter return undefined:
$scope.imageUpload = function(files) {
console.log($scope.editable); // undefined
};
Thanks!
You need to add code like above in after success.
var uploaded_file_name = data.file_name;
var file_path = '/assets/uploads/'+uploaded_file_name;
var editor = $.summernote.eventHandler.getModule();
editor.insertImage(vm.editable, file_path, uploaded_file_name);
Related
I'm using TinyMCE 5 with PHP 7.
Currently:
1. images_upload_handler (working)
Following the TinyMCE guide on Drag-in uploading images, and my own PHP upload AJAX handler, I got an image to upload successfully to my uploads directory:
This correctly uploads the file and keeps the correct name, using AJAX.
It uses a function for images_upload_handler, calling my AJAX handler.
2. file_picker_callback (incomplete)
Following the TinyMCE demo on uploading files, I got these two toolbar buttons (image, media) to show an upload button in their dialogs:
This works for image, not media.
It uses a function for file_picker_callback, uploading its own way.
3. The problem
I can't get the file_picker_callback from 2. to upload from media and I want it to use my own AJAX upload handler anyway, which I can't.
Using the image tool to upload, it will save the file after clicking "Save" in the dialog. But, when used in the media tool, it will not upload or insert anything at all.
It seems that this JavaScript demo provided by TinyMCE has a heavy interaction with the TinyMCE API itself. It has a system of caching and blobs to find the file that TinyMCE uploaded on its own. So pure AJAX-JS knowledge isn't sufficient to tell me how to tell TinyMCE to use my own AJAX upload PHP file. I'd rather just override TinyMCE's upload handler in file_picker_callback so I can use my own PHP upload script to be compatible with the rest of my app.
Goal:
I need a function for file_picker_callback (the file upload button) to use my own AJAX upload handler and preserve the name just as images_upload_handler succeeds in doing.
I am not worried about filename and mimetype validation; I plan to have PHP sanitize and filter later on.
This Question addresses another file uploader and the problem of TinyMCE 4 solutions not always working with TinyMCE 5.
This Question is about image description, and only for images; I want to upload any filetype.
I do not want any dependencies, not even jQuery. Vanilla JS only.
Current Code:
| upload.php :
$temp_file = $_FILES['file']['tmp_name'];
$file_path_dest = 'uploads/'.$_FILES['file']['name'];
move_uploaded_file($temp_file, $file_path_dest);
$json_file_is_here = json_encode(array('filepath' => $file_path_dest));
echo $json_file_is_here;
| tinyinit.js :
tinymce.init({
selector: 'textarea',
plugins: [ 'image media imagetools', ],
automatic_uploads: true,
images_reuse_filename: true,
images_upload_url: 'upload.php',
// From #1. Successful AJAX Upload
images_upload_handler: function(fileHere, success, fail) {
var ajax = new XMLHttpRequest();
ajax.withCredentials = false;
ajax.open('post', 'upload.php');
ajax.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
ajax.onload = function() {
if (ajax.status == 200) {
if ( (!JSON.parse(ajax.responseText))
|| (typeof JSON.parse(ajax.responseText).filepath != 'string') ) {
fail('Invalid: <code>'+ajax.responseText+'</code>');
return;
}
success(JSON.parse(ajax.responseText).filepath);
} else {
fail('Upload error: <code>'+ajax.status+'</code>');
return;
}
};
var fileInfo = new FormData();
fileInfo.append('file', fileHere.blob(), fileHere.filename());
ajax.send(fileInfo);
},
file_browser_callback_types: 'file image media',
file_picker_types: 'file image media',
// From #2. Neither uploads from "media" nor uses my upload handler
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(file.name, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
}
});
Editing #Aulia's Answer :
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
// FormData
var fd = new FormData();
var files = file;
fd.append('filetype',meta.filetype);
fd.append("file",files);
var filename = "";
// AJAX
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/your-endpoint');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
alert('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
alert('Invalid JSON: ' + xhr.responseText);
return;
}
filename = json.location;
reader.onload = function(e) {
cb(filename);
};
reader.readAsDataURL(file);
};
xhr.send(fd);
return
};
input.click();
}
In the configuration you've provided, #2 doesn't have any logic to upload the data to your server. The code from Tiny's documentation you've copied is just for demo purposes and won't allow you to upload files to Tiny's servers.
You will need to setup the file_picker_callback callback to send data similar to images_upload_handler. On your server, you will need to send the URI and title in the response so the following line will be fulfilled:
cb(blobInfo.blobUri(), { title: file.name });
Hope it will helps mate, make your file_picker_callback looks like below codes
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
// FormData
var fd = new FormData();
var files = file;
fd.append('filetype',meta.filetype);
fd.append("file",files);
var filename = "";
// AJAX
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/your-endpoint');
xhr.onload = function() {
var json;
if (xhr.status != 200) {
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);
filename = json.location;
};
xhr.send(fd);
reader.onload = function(e) {
cb(filename);
};
reader.readAsDataURL(file);
return
};
input.click();
},
Hi I am using Ajax Upload JS 3.5 is there a way to make a progress upon uploading of image / File ?. All I see in my net is by using the <input type="file"> button and my project is not a bootstrap.
Here is my currently code
jQuery(document).ready(function () {
var extension = "";
var btnUploadDrvr = $("#btnFitaDocBrowse");
var hidFilenameDrvr = $("#imgFitaDoc");
var hidDoccFrame = $("#frmFitaDoc");
InitAjaxUpload(btnUploadDrvr, hidFilenameDrvr, hidDoccFrame );
function InitAjaxUpload(btnUpload, imgHolder, hidDoccFrame) {
new AjaxUpload(btnUpload, {
action: '../UploadDownload/UploadLocalPic',
data: '',
name: 'uploadfile',
onSubmit: function (file, ext) {
extension = ext[0];
if (!(ext && /^(jpg|png|jpeg|gif|pdf|PDF)$/.test(ext))) {
alert("File format is not supported.");
return false;
}
},
onComplete: function (file, response) {
//Add uploaded file to list
if (response !== "failed") {
$("#frmFitaDoc").attr('src', 'data:application/pdf;base64,' + response);
}
}
});
}
});
And I saw this can this be possible to embed in my code?.
I have been searching online looking for the answer to this problem but I cannot seem to find anything that works, I have the following Controller code:
[HttpPost]
public ActionResult UploadFiles()
{
// If files exist
if (Request.Files != null && Request.Files.Count > 0)
{
// ** Do stuff
return Json(new { result = true, responseText = "File(s) uploaded successfully" });
}
// Return no files selected
return Json(new { result = false, responseText = "No files selected" });
}
And following code in my cshtml page which works fine and the controller can see the files that I upload:
<input type="file" name="files" id="files" accept="image/*;capture=camera" multiple>
<button type="button" onclick="submitform()">Submit</button>
<script>
function submitform(){
// Get files from upload
var files = $("#files").get(0).files;
// Create form data object
var fileData = new FormData();
// Loop over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Send files to controller
var xhr = new XMLHttpRequest();
xhr.open("POST", "/Quotes/QuoteFiles/UploadFiles", false);
xhr.send(fileData);
}
</script>
However when I try and change this to work using an Ajax call as shown below then Request.Files in the Controller always has no files. The only bit I have changed is the "Send files to controller" part:
<input type="file" name="files" id="files" accept="image/*;capture=camera" multiple>
<button type="button" onclick="submitform()">Submit</button>
<script>
function submitform(){
// Get files from upload
var files = $("#files").get(0).files;
// Create form data object
var fileData = new FormData();
// Loop over all files and add it to FormData object
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
// Send files to controller
$.ajax({
url: '/Quotes/QuoteFiles/UploadFiles',
type: "POST",
contentType: false, // Not to set any content header
processData: false, // Not to process data
data: fileData,
success: function (result) {
alert(result);
},
error: function (err) {
alert(err.statusText);
}
});
}
</script>
I am running this in Google Chrome but I have tried IE 11 and Edge but not of them work. Can anyone tell me what I am doing wrong?
try using a fileReader instead of a formData and change the mimetype to 'text/plain; charset=x-user-defined-binary'
https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications#Example_Uploading_a_user-selected_file
I have finally found what was causing this issue, I have the following code on my _Layout.cshtml page which is there to automatically send the AntiForgeryToken on any ajax requests I make, this appears to be causing the problem because once I remove it Request.Files is not empty. I now need to see if I can find a way to add this code back in where it will not stop file uploads working:
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || event.contentType) {
request.setRequestHeader("Content-Type", opt.contentType);
}
}
});
});
**** EDIT ****
I have now reworked this as shown below to add 'if(opt.data != "[object FormData]"' which resolves the issue by not calling the code if it is a file upload:
$(document).ready(function () {
var securityToken = $('[name=__RequestVerificationToken]').val();
$(document).ajaxSend(function (event, request, opt) {
if (opt.hasContent && securityToken) { // handle all verbs with content
// If not "FormData" (i.e. not a file upload)
if (opt.data != "[object FormData]")
{
var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(securityToken);
opt.data = opt.data ? [opt.data, tokenParam].join("&") : tokenParam;
// ensure Content-Type header is present!
if (opt.contentType !== false || event.contentType) {
request.setRequestHeader("Content-Type", opt.contentType);
}
}
}
});
});
Using blueimp, I'm making a file upload module and I will show an image thumbnail before people upload the image.
My code contains the following:
$('.fileupload').fileupload({
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(jpe?g|png)$/i,
maxNumberOfFiles: 1,
maxFileSize: 3000000,//3MB
loadImageMaxFileSize: 3000000,//3MB
}).on('fileuploadsubmit', function (e, data) {
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('.files');
$.each(data.files, function (index, file) {
// ファイル情報を表示する
var node = $('<p/>')
.append($('<span/>').text(file.name));
// プレビューを表示する
if (!index) {
node.append('<br>');
if((/\.(jpe?g|png)$/i).test(data.files[0].name))
{
node.append('<img class= "uploaded-image" src="'
+ URL.createObjectURL(data.files[0]) + '"/><br>');
}
node.append(uploadButton.clone(true).data(data))
.append(cancelButton);
}
node.appendTo(data.context);
});
}) // .on(... code following
It works well, but if people change a GIF file extension to ".jpeg" and upload it, the blob will also work well to show the GIF and, I think it's not safe. Is there a way not let blob to show the thumbnail In this case?
When submit the file, I'm checking the file in the server side if the file is really an image file (although it has a valid extension).
(this link helped me)
The code below worked well:
if (!index) {
node.append('<br>');
if((/\.(jpe?g|png)$/i).test(data.files[0].name))
{
if (window.FileReader && window.Blob)
{
var blob = data.files[0]; // See step 1 above
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
var arr = (new Uint8Array(e.target.result)).subarray(0, 4);
var header = "";
for(var i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
if((header == "89504e47") || (header.substr(0,6) == "ffd8ff"))
{
$("button.upload").before('<img class= "uploaded-image" src="' + URL.createObjectURL(data.files[0]) + '"/><br>');
$(".file_upload").attr("style", "height: 600px; overflow-y: auto");
}
else
{
$("button.upload").prop('disabled', true);
var error = $('<span class="text-danger"/>').text(msg[4]);
$('.files').append('<br>').append(error);
}
};
fileReader.readAsArrayBuffer(blob);
}
}
node.append(uploadButton.clone(true).data(data))
.append(cancelButton);
}
I uses elFinder laravel package file Manager with ckeditor. I follow all Instructions step and all things work except one.
When I click on image button in ckEditor to select (or upload) an Image , on the upload tab after select an image from my computer and click Send it to the Server button NotFoundHttpException in RouteCollection.php line 161 shown and upload fails.
this is ckEditor initialization code :
<textarea name="content_fa" id="fa_post_content" class="form-control"
rows="10"></textarea>
<script>
var fa_post_content = CKEDITOR.replace('fa_post_content', {
toolbar: 'admin_mode',
filebrowserBrowseUrl : '{{route('elfinder.ckeditor')}}',
filebrowserUploadUrl : '/elfinder/connector.php?cmd=upload'
});
</script>
According to This Issue , I add filebrowserUploadUrl option as you see above. but this not work too.
How can I solve this ?
This code (+ DnD upload) using demo site is here.
CKEDITOR.on('dialogDefinition', function (event) {
var editor = event.editor,
dialogDefinition = event.data.definition,
tabCount = dialogDefinition.contents.length,
uploadButton, submitButton, inputId,
elfUrl = editor.config.filebrowserUploadUrl,
// elFinder configs
elfDirHashMap = { // Dialog name / elFinder holder hash Map
image : '',
flash : '',
files : '',
link : '',
fb : 'l1_Lw' // fallback target
},
customData = {}; // any custom data to post
for (var i = 0; i < tabCount; i++) {
uploadButton = dialogDefinition.contents[i].get('upload');
submitButton = dialogDefinition.contents[i].get('uploadButton');
if (uploadButton !== null && submitButton !== null) {
uploadButton.hidden = false;
submitButton.hidden = false;
uploadButton.onChange = function() {
inputId = this.domId;
}
submitButton.onClick = function(e) {
dialogName = CKEDITOR.dialog.getCurrent()._.name;
var target = elfDirHashMap[dialogName]? elfDirHashMap[dialogName] : elfDirHashMap['fb'],
name = $('#'+inputId),
input = name.find('iframe').contents().find('form').find('input:file'),
error = function(err) {
alert(err.replace('<br>', '\n'));
};
if (input.val()) {
var fd = new FormData();
fd.append('cmd', 'upload');
fd.append('overwrite', 0); // disable upload overwrite to make to increment file name
fd.append('target', target);
$.each(customData, function(key, val) {
fd.append(key, val);
});
fd.append('upload[]', input[0].files[0]);
$.ajax({
url: elfUrl,
type: 'POST',
data: fd,
processData: false,
contentType: false,
dataType: 'json'
})
.done(function( data ) {
if (data.added && data.added[0]) {
var url = data.added[0].url;
var dialog = CKEDITOR.dialog.getCurrent();
if (dialogName == 'image') {
var urlObj = 'txtUrl'
} else if (dialogName == 'flash') {
var urlObj = 'src'
} else if (dialogName == 'files' || dialogName == 'link') {
var urlObj = 'url'
} else {
return;
}
dialog.selectPage('info');
dialog.setValueOf(dialog._.currentTabId, urlObj, url);
} else {
error(data.error || data.warning || 'errUploadFile');
}
})
.fail(function() {
error('errUploadFile');
})
.always(function() {
input.val('');
});
}
return false;
}
}
}
});
For anyone running into this issue now, the thing that resolved it for me was setting filebrowserBrowseUrl. The mistake I was making was setting filebrowserUploadUrl instead of the filebrowserBrowseUrl. Elfinder handles the upload inside itself, so you should not have to use the 'send to the server' button at all, just the browse server button.
So the ckeditor code looked like such
CKEDITOR.replace('your-id-here', {
filebrowserBrowseUrl: '/elfinder/ckeditor',
}
);
noting to replace your-id-here with your own id.