Having an issue with uploading images on Tiny. I want to upload the images to folder /images/owner/ I don't want a blob, but rather to upload full files.
I can upload to file_upload.php no problem from test.html. Containing a text input and a file input only. file_upload.php looks like this ...
<?php
/***************************************************
* Only these origins are allowed to upload images *
***************************************************/
$accepted_origins = array("http://localhost", "http://192.168.1.1", "https://example.com/");
/*********************************************
* Change this line to set the upload folder *
*********************************************/
$owner_id=$_POST["owner"];
//$owner_id='15601a2cc3d5b2';
$imageFolder = "images/". $owner_id . "/";
// Don't attempt to process the upload on an OPTIONS request
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("Access-Control-Allow-Methods: POST, OPTIONS");
return;
}
reset($_FILES);
$temp = current($_FILES);
if (is_uploaded_file($temp['tmp_name'])){
// Sanitize input
if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) {
header("HTTP/1.1 400 Invalid file name.");
return;
}
// Verify extension
if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
header("HTTP/1.1 400 Invalid extension.");
return;
}
// Accept upload if there was no origin, or if it is an accepted origin
$filetowrite = $imageFolder . $temp['name'];
move_uploaded_file($temp['tmp_name'], $filetowrite);
// Determine the base URL
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https://" : "http://";
$baseurl = $protocol . $_SERVER["HTTP_HOST"] . rtrim(dirname($_SERVER['REQUEST_URI']), "/") . "/";
// Respond to the successful upload with JSON.
// Use a location key to specify the path to the saved image resource.
// { location : '/your/uploaded/image/file'}
echo json_encode(array('location' => $baseurl . $filetowrite));
} else {
// Notify editor that the upload failed
header("HTTP/1.1 500 Server Error");
}
?>
This Tiny JS code is on my editor.php page. I don't want a blob that can't be linked to. I want to send an email newsletter and only proper files/images on the server will render...
<script>
tinymce.init({
selector: '#mytextarea',
images_upload_handler: images_upload_handler,
plugins: 'image code',
toolbar: 'undo redo | link image',
/* enable title field in the Image dialog*/
image_title: true,
/* enable automatic uploads of images represented by blob or data URIs*/
automatic_uploads: true,
/*
URL of our upload handler (for more details check: https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_url)
images_upload_url: './js/tinymce/postAcceptor.php',
here we add custom filepicker only to Image dialog
*/
file_picker_types: 'image',
/* and here's our custom image picker*/
file_picker_callback: function (cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
/*
Note: In modern browsers input[type=\"file\"] is functional without
even adding it to the DOM, but that might not be the case in some older
or quirky browsers like IE, so you might want to add it to the DOM
just in case, and visually hide it. And do not forget do remove it
once you do not need it anymore.
*/
input.onchange = function () {
var file = this.files[0];
var reader = new FileReader();
reader.onload = function () {
/*
Note: Now we need to register the blob in TinyMCEs image blob
registry. In the next release this part hopefully won't be
necessary, as we are looking to handle it internally.
*/
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
/* call the callback and populate the Title field with the file name */
cb(blobInfo.blobUri(), { title: file.name });
};
reader.readAsDataURL(file);
};
input.click();
},
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
function images_upload_handler (blobInfo, success, failure, progress) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST','https://example.com/myfolder/file-upload.php');
xhr.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
xhr.onload = function() {
var 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('owner','" . $owner_id . "');
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
};
When i do this from chrome web dev ...
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST','https://example.com/myfolder/file-upload.php');
formData = new FormData();
formData.append('owner','ddddddddd');
formData.append('file', '/home/me/Desktop/image/mail.png');
xhr.send(formData);
I get array(0) {}
I can't send both values, owner and file. I've stacked them in the correct order.
Also have to click upload on the Tiny editor image popup, when i use General it gives me a blob.
No luck. Sorry if this post is kinda verbose. Thought you'd need all the code to help...
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();
},
By default tinymce image has no browse button where you can click and see a dialog box to choose an image. In my code am trying to add image picker button to tinymce but am finding it difficult to combine it with the images_upload_handler. And lastly how do i use the success callback to update images_upload_base_path.
tinymce.init({
...
images_upload_handler: function (blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', "postAcceptor.php");
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);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
}
});
I don't really understand why, but for me images_upload_handler not works as well... =(
Use file_picker_callback instead, like in this example that I found:
https://codepen.io/nirajmchauhan/pen/EjQLpV
I am trying to make a facebook like image uploader with the most basic methods. I select the multiple images on the input and then it creates the per file progress bars with names. It shows it's loading but it doesn't send to the upload.php file. I have the HTML code section:
<div class="container">
<h1>Uploader</h1>
<hr>
<form action="#" id="image_form">
<input type="file" id='image' name="image" multiple>
</form>
<div class="container">
<div class="filelist">
</div>
<ul id="uploads">
</ul>
</div>
Then I have my javascript. The progress bars get created with the file names and the progress is tracked. I have tried it with largish files and it does take a long while to upload. Progress bar shows this accurately.
$('#image').change(function (event) {
var files = this.files;
// iterate over each file to upload, send a request, and attach progress event
for (var i = 0, file; file = files[i]; i++) {
var li = $("<li>" + file.name + "<div class='progress progress-striped active'><div class='progress-bar' style='width:0%'>" + file.size + "</div></div></li>");
// add the LI to the list of uploading files
$("#uploads").append(li);
// fade in the LI instead of just showing it
li.hide().fadeIn();
var xhr = new XMLHttpRequest();
xhr.upload.li = li;
xhr.upload.addEventListener('progress', function(e) {
var percent = parseInt(e.loaded / e.total * 100);
this.li.find(".progress-bar").width(percent+'%');
}, false);
// setup and send the file
xhr.open('POST', 'upload.php', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
}
});
I have been struggling with this piece of code for the last week and have been through almost every topic on this site without success. Please could someone help me figure out why I can't post the file details to the php script.
I'm using this code to post files to PHP:
function postFile(action, file, postFileName) {
var fPostName = typeof postFileName === 'undefined' ? 'file' : postFileName;
/* Create a FormData instance */
var formData = new FormData();
/* Add the file */
formData.append(fPostName, file);
var requestUrl = rootUrl + action;
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('POST', requestUrl);
/* handlers */
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
console.log(formData);
/* send request */
xhr.send(formData);
});
}
// Sample usage
* <<< FILE upload >>>>>>
* var file = document.getElementById('f').files[0];
* console.log(file);
* postFile('your_processing_script.php', file).then(function (response) {
* console.log(response);
* },function (er) {
* console.log(er);
* });
and then in PHP you should have:
$_FILES["file"] or $_FILES[postFileName]
Hope this helps you.
Cheers
I have an image created with a JavaScript Blob which I need to upload to a PHP script.
My JavaScript upload function...
function upload(blobOrFile) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://requestb.in/17m14c51', true);
xhr.onload = function(e) {
//
};
// Listen to the upload progress.
//var progressBar = document.querySelector('progress');
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
console.log((e.loaded / e.total) * 100);
//progressBar.textContent = progressBar.value; // Fallback for unsupported browsers.
}
};
xhr.send(blobOrFile);
}
This URL http://requestb.in/17m14c51?inspect shows the data that this code is posting.
My Image is coming in as an image. I am not sure how to access this image in my PHP script though as I do not see any form or file name, maybe I am missing it?
Previously my PHP had the image come in as Base64 so this PHP below did the upload...
function base64_to_jpeg($base64_string, $output_file) {
//$output_file_new= $output_file.'-'.md5(time().uniqid()).'.jpg';
$output_file_new= $output_file;
$ifp = fopen($output_file_new, "wb");
$base64_string2 = urldecode($base64_string);
$data = explode(',', $base64_string2);
$decoded = base64_decode($data[1]);
fwrite($ifp, $decoded);
fclose($ifp);
echo json_encode(array('img_url' => $output_file_new, 'headers' => parseRequestHeaders()));
//return $output_file_new;
}
Now that I am not getting it as Base64, how can I save it in my PHP?
We followed the instructions on this tutorial but for some reason, the upload button (the search folder icon next to the image URL) on the image dialog does not show:
http://www.tinymce.com/wiki.php/Handling_Asynchronous_Image_Uploads
We've tried with just the images_upload_url option as well as all the options, but the upload icon never shows:
tinymce.init({
...
images_upload_url: "postAcceptor.php",
images_upload_base_path: "/some/basepath", //optional
images_upload_credentials: true //optional
});
The articles suggest that all you really need is specify the images_upload_url and TinyMCE will allow image uploads.
We are running 4.2.5. This feature is available since 4.2.0. I've confirmed with TinyMCE parent company (Ephox) that the image upload feature is a community version feature. So has anyone gotten this to work?
It is not supposed to show you an image picker icon.
It uploads images from files you paste into the editor.
If you want file picker you should use the file_picker_callback.
If you want a file picker icon you need to insert image into your toolbar.
***JS***
<script>
function example_image_upload_handler (blobInfo, success, failure, progress) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', '/home/uplaodimage');
xhr.upload.onprogress = function (e) {
progress(e.loaded / e.total * 100);
};
xhr.onload = function() {
var 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);
};
</script>
<script>
tinymce.init({ selector:'textarea.editor',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
images_upload_handler: example_image_upload_handler,
convert_urls: false,
</script>
PHP
$accepted_origins = array("http://localhost","https://yoursite.com");
// Images upload path
$imageFolder = dirname(BASEPATH) . "/uploads/";
reset($_FILES);
$temp = current($_FILES);
if(is_uploaded_file($temp['tmp_name'])){
if(isset($_SERVER['HTTP_ORIGIN'])){
// Same-origin requests won't set an origin. If the origin is set, it must be valid.
if(in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)){
header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
}else{
header("HTTP/1.1 403 Origin Denied");
return;
}
}
// Sanitize input
if(preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])){
header("HTTP/1.1 400 Invalid file name.");
return;
}
// Verify extension
if(!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))){
header("HTTP/1.1 400 Invalid extension.");
return;
}
// Accept upload if there was no origin, or if it is an accepted origin
$immage_name= $temp['name'];
$filetowrite = $imageFolder . $immage_name;
move_uploaded_file($temp['tmp_name'], $filetowrite);
// Respond to the successful upload with JSON.
echo json_encode(array('location' => '/uploads/'.$immage_name));
} else {
// Notify editor that the upload failed
header("HTTP/1.1 500 Server Error");
}