Customizing image uploading in TinyMCE - file-upload

I have an ASP.NET Web API web service which I want to use for file uploading. The way I do this is that the client posts a JSON object to the service at http://myserver.com/api/images/upload .
The object would contain a base64 string representation of the image, plus some metadata, e.g:
{ companyId: 12345, image: "someBase64encodedStringRepresentingTheImage" }
I would like to use TinyMCE on the client side, but I can't figure out how to customize it such that images are uploaded to the server in that format. (Actually, it doesn't seem like TinyMCE comes with an image uploader at all)

TinyMCE 4.2+ actually has its own built in process for handling the upload of images that you place in the editor:
https://www.tinymce.com/docs/advanced/handle-async-image-uploads/
The basic process is that TinyMCE will create a separate HTTP POST for each image that you insert into the editor. It will send that image to a URL of your choosing (via HTTP POST) based on the setting of the images_upload_url option in your init.
The image handler at the URL referenced in the images_upload_url (which you have to create) has to do whatever needs to be done to "store" the image in your application. That could mean something like:
Store the item in a folder on your web server
Store the item in a database
Store the item in an asset management system
...regardless of where you choose to store the image your image handler needs to return a single line of JSON telling TinyMCE the new location of the image. As referenced in the TinyMCE documentation this might look like:
{ location : '/uploaded/image/path/image.png' }
TinyMCE will then update the image's src attribute to the value you return. If you use the images_upload_base_path setting in the init that will be prepended to the returned location.
The net here is that TinyMCE knows when an embedded image exists in your content but it can't possibly know what to do with that image in the context of your application so that job (the "image handler") is something you must create.
There is an option for you to write your own image handler if the default one is not sufficient:
https://www.tinymce.com/docs/configure/file-image-upload/#images_upload_handler
I would recommend trying to use the uploader that comes with TinyMCE so you don't have to write and maintain your own code going forward (always easier) but if the built in code is not appropriate you can indeed replace it with your own function.

Related

How can I lazy-load images with Cloudinary and Strapi?

I am working on a project using Gatsby, Strapi and Cloudinary. I am deploying the frontend on Netlify and the Strapi app on Heroku (with the addition of a Postgresql database instance).
I have been searching for weeks now and but I cannot seem to find a way to lazy-load images sourced through Cloudinary.
I have replaced the default rich content editor on Strapi with the ckeditor so editors can add photos to their content. These are automatically uploaded and served by Cloudinary.
My question is, is there a way to lazy-load the images, and if so, should this be done when serving them from Cloudinary, should I do this as a Strapi middleware or simply through Gatsby?
Note: I am not sourcing the images anywhere on the front-end since it's parsed as html from Strapi. All I'm currently doing in passing the fetched content to a div using
dangerouslySetInnerHtml.
With dangerouslySetInnerHtml directive you are inserting whatever is inside your rich text as HTML content so you lose control of customizing the behavior of that content. Hence, it will be rendered all at once.
There's no built-in way of doing this except by parsing your rich text with a third-party dependency (which I haven't been able to find)/custom method that will give you the capability of wrapping your images with any custom component. The idea, either way, is to parse your rich text blocks to customize the output.
In addition, check if the images tag (<img>) comes with the loading=lazy property attached:
<img src="image.jpg" alt="..." loading="lazy">

How to create a zone to drop/select an image for uploading on Ember.js?

I have a form and I'm using it to save() an ember model to the database.
This model should also have an image, so I want to create a zone like the one below:
User should be able to drag and drop a file from its file browser or selecting it using the blue button.
Also, how do I actually upload the file along with the other model properties?
You could use EmberDroplet addon and customize it to your needs (for example you can set file limit to 1 and customize CSS). To upload file you have to specify url property, eg:
App.XDropletComponent = Ember.Component.extend(Droplet, {
url: location.origin + '/upload'
});
And in your API endpoint (on server side) you could handle file upload + setting image path on model in database (simple string attribute with URL to your image so you can use it later in your application).
Then you could use didUpload hook to refresh your model (this way you get back image URL after upload).
Or you can use the filepicker.io Ember addon.
Source code and usage here.
Quick reference below.
Template:
{{ember-filepicker pickerOptions=pickerOptions
storeOptions=storeOptions onSelection='fileSelected'
onClose='onClose' onError='onError'}}
Controller actions:
fileSelected: function(params){
//save the params.url to your model
//the image is stored by filepicker on Amazon S3
},

ImageResizer and Images delivered as byte stream

We have an umbraco MVC website with which we are trying to use ImageResizer. In order to keep uploaded files out of a publicly accessible area, images are stored outside of the webroot and we use a controller to deliver them to browswer (e.g. an image url on a page would be something like <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?" alt="Here there be an image, yarrr!">)
The ShowImage action is something like:
public ActionResult ShowImage(int id)
{
using (DBContext db = new DBContext())
{
Attachment a = db.Attachments.FirstOrDefault(x.ID == id);
if (a != null)
{
byte[] file = System.IO.File.ReadAllBytes(System.IO.Path.Combine(System.Configuration.ConfigurationManager.AppSettings["UploadPath"], a.Path, a.FileName));
return this.File(file, a.MimeType);
}
}
}
If we use the URL API on a publicly accessible image (e.g. <img src="/images/kitty.jpg?width=33&height=33&mode=crop" alt="Here there be kitties, yarrr!">), then everything works as expected.
However, we've tried using the URL API to resize our images delivered by the controller to no avail (e.g. <img src="/umbraco/surface/AttachmentSurface/ShowImage/999?width=33&height=33&mode=crop" alt="Here there be an image, yarrr!">).
Is the only way around this to use the Managed API and resize the image before delivering? I seem to remember the documentation saying something to the effect that it's a bad idea to use it from within an MVC Action...
Thanks for any help.
ImageResizer doesn't operate as middleware, unfortunately, as middleware can't access the right resources in order to do a good job. It controls the request from beginning to end, and tries to integrate smoothly with existing authentication, URL rewrite, and CMS modules. That's why it doesn't work on an MVC action. It wouldn't be able to cache to disk, and it would have a severe performance overhead from double-buffering.
If you're just trying to block access to original files, you could do that in a variety of ways without moving the files outside of the root (UrlAuthorization, AuthorizeRequest event, disabling handlers for that folder, etc).
If you want to control where the images come from, you should implement an IVirtualImageProvider class. ImageResizer does include an IVirtualImageProvider plugin (named VirtualFolder) that can provide access to external/off root files. If your needs are basic, give that a try, and drop the MVC action.

Get background variable value in content scripts

I have a var in background page (for example var x = 23). How I can get this variable in my content script? I tried this in content.js:
chrome.extension.getBackgroundPage().x;
But it doesn't work.
Send your data with messages, and listen on the receiving side.
Messages
Since content scripts run in the context of a web page and not the extension, they often need some way of communicating with the rest of the extension. For example, an RSS reader extension might use content scripts to detect the presence of an RSS feed on a page, then notify the background page in order to display a page action icon for that page.
You can not use chrome.extension.getBackgroundPage() in content scripts, it is not supported, as an alternative use epoch answer for message communication.
References:
Support for Content Scripts

how to read/parse dynamically generated web content?

I need to find a way to write a program (in any language) that will connect to a website and read dynamically generated data from the website.
Note that it's dynamically generated--it's not enough to get the source html, because the data I'm interested in is generated via javascript that references back-end code. So when i view the webpage source, I can't see the data. (For example, go to google, and do a search. Check the source code on the search results page. Very little of the data your browser is displaying is reflected in the source--most of it is dynamically generated. I need some way to access this data.)
Pick a language and environment that includes an HTML renderer (e.g. .NET and the WebBrowser control). Use the HTML renderer to get the URL and produce an HTML DOM in memory (making sure that scripting is enabled). Read the contents of the HTML DOM after the renderer has done its work.
Example (you'll need to do this inside a System.Windows.Form derived class):
WebBrowser browser = new WebBrowser();
browser.Navigate("http://www.google.com");
HtmlDocument document = browser.Document;
// extract what you want from the document
I used to have a Perl program to access Mapguide.com to get the drive direction from one location to another location. I parsed the returned page and save to database. If the source never change their format, it is OK. the problem is the source format often change, your parser also need change.
A simple thought: if we're talking about AJAX, you can rather look up the urls for the dynamic data. Then you can use the javascript on the page you're talking about to reformat this.
If you have Firefox/greasemonkey making a DOM dumper should be a simple matter.