We have made a custom image cropper.
The idea is that it saves a query string in a field in the item.
Then on rendering we add that query string to the image url.
We added a getMediaStream pipeline. Inside this pipeline we crop the image using ImageProcessor based on the querystring that the image has.
This all works... once.
After it worked once the image is in the media cache and we never get back inside the getMediaStream pipeline. Because when you recrop, you don't change the image but you change that querystring.
We are searching for a way that when we save a new crop, we clear the media cache from that image.
We have tried the following:
var mediaItem = new MediaItem(imageField.MediaItem);
var media = MediaManager.GetMedia(mediaItem);
var mediaOptions = new MediaOptions();
var mediaStream = MediaManager.Cache.GetStream(media, mediaOptions);
MediaStream cachedStream = null;
MediaManager.Cache.AddStream(media, mediaOptions, mediaStream, out cachedStream);
We get the media cache stream and try setting it to zero, but that gives us the following exception: Could not create the buffer file needed for stream sharing
Any ideas if it's possible to clear a single item from the media cache?
I don't think you need to remove a single item from the cache. Sitecore stores one image in the cache per unique request. If you have genuinely updated the querystring that is used to request the image then Sitecore should call the getmediastream pipeline again.
My guess is that your custom querystring is not actually being passed as part of the request.
Sitecore stores a ini file alongside the cached images, It has a section per image request and stores the querystring that was requested. Bottom line, if your querystring is unique then you should hit the pipeline.
Related
In PowerApps, let's say I have a field of "image" type called foo_imagefield on a table foo_testtable. I want to access the full size of this image in a plugin or console app using IOrganizationService. I can retrieve the record with the image field as follows:
string[] columns = { "foo_imagefield" };
Entity testRecord = Service.Retrieve("foo_testtable", new Guid("4B365AFD-B31C-EC11-B6E6-000D3A4EA781"), new ColumnSet(columns));
Now I can get the image bytes from the field:
byte[] imageBytes = testRecord.GetAttributeValue<byte[]>("foo_imagefield");
Great, except this only seems to give me the thumbnail version of the image (I believe PowerApps reduces it to 144px * 144px). It's super tiny. I know I can get the full version via a URL (e.g. https://myinstance.crm.dynamics.com/Image/download.aspx?Entity=foo_testtable&Attribute=foo_imagefield&Id=4b365afd-b31c-ec11-b6e6-000d3a4ea781&Timestamp=637801267356898020&Full=true as long as you are authenticated). I can also get the full version via rest API (e.g. GET /api/data/v9.1/<entity-type(id)>/<image-attribute-name>/$value?size=full). But being that I'm doing this in a plugin, I don't want to have to authenticate again.
Is there any way to get the full image with Microsoft.CRM.SDK IOrganizationService?
I'm creating a mockup file upload tool for a community site using Fine Uploader.
I've got the session set up to retrieve the initial files from the server along with a thumbnail url.
It all works great, however the rendering of the thumbnails is really slow.
I can't work out why. So I hard-coded to use a very small thumbnail for each of the four files. This made no difference.
The server side not the issue. The information is coming back very quickly.
Am I doing something wrong? Why is fineuploader so slow? Here's screen grab. It's taking four seconds to render the four thumbnails.
I'm using latest chrome. It's a NancyFX project on a fairly powerful machine. Rending other pages with big images on them is snappy.
Client side code:
thumbnails: {
placeholders: {
waitingPath: '/Content/js/fine-uploader/placeholders/waiting-generic.png',
notAvailablePath: '/Content/js/fine-uploader/placeholders/not_available-generic.png'
}
},
session: {
endpoint: "/getfiles/FlickaId/342"
},
Server side code:
// Fine uploader makes session request to get existing files
Get["/getfiles/FlickaId/{FlickaId}"] = parameters =>
{
//get the image files from the server
var i = FilesDatabase.GetFlickaImagesById(parameters.FlickaId);
// list to hold the files
var list = new List<UploadedFiles>();
// build the response data object list
foreach (var imageFile in i)
{
var f = new UploadedFiles();
f.name = "test-thumb-small.jpg"; // imageFile.ImageFileName;
f.size = 1;
f.uuid = imageFile.FileGuid;
f.thumbnailUrl = "/Content/images/flickabase/thumbnails/" + "test-thumb-small.jpg"; // imageFile.ImageFileName;
list.Add(f);
}
return Response.AsJson(list); // our model is serialised by Nancy as Json!
};
This is by design, and was implemented both to prevent the UI thread from being flooded with the image scaling logic and to prevent a memory leak issue specific to Chrome. This is explained in the thumbnails and previews section of the documentation, specifically in the "performance considerations" area:
For browsers that support client-generated image previews (qq.supportedFeatures.imagePreviews === true), a configurable pause between template-generated previews is in effect. This is to prevent the complex process of generating previews from overwhelming the client machine's CPU for a lengthy amount of time. Without this limit in place, the browser's UI thread runs the risk of blocking, preventing any user interaction (scrolling, etc) until all previews have been generated.
You can adjust or remove this pause via the thumbnails option, but I suggest you not do this unless you are sure users will not drop a large number of complex image files.
In xamarin forms we can create images like this:
Image i = new Image { Source = "http://www.foo.com/foo.jpg };
After adding this to layout if url returns an image it will display it. What I want to now is is there a way to know if ths Url is an actual image. Otherwise I am going to show an default image.
Regards.
Edit
I have created a function:
public string GetImageSourceOrDefault(string orgUrl)
{
var req = (HttpWebRequest)WebRequest.Create(orgUrl);
req.Method = "HEAD";
try
{
using (var resp = req.GetResponse())
{
bool res = resp.ContentType.ToLower(CultureInfo.InvariantCulture)
.StartsWith("image/");
if (res)
return orgUrl;
else
return "defualt_logo.jpg";
}
}
catch
{
return "default_logo.jpg";
}
}
This function does the trick. However, for every image it does a request. I have a listview which shows like 220 entries. Using this method messed up the time that listview gets loaded.
Note: this function is natively called using dependency injection.
Maybe further improvements will do. Any ideas?
FFImageLoading CachedImage supports Loading and Error Placeholders (and much more). It's basically a API compatible replacement for Image with additional properties. You could try that.
var cachedImage = new CachedImage() {
LoadingPlaceholder = "Loading.png",
ErrorPlaceholder = "Error.png"
};
https://github.com/molinch/FFImageLoading
With Xamarin.Forms UriImageSource you can specify different caching length, and whether caching is used by using the properties CacheValidity and CachingEnabled.
By default it will automatically cache results for 1 day on the local storage of the device.
In your function, as you mention, you are downloading the image every single time.
You have no current functionality that is storing and caching the result for later re-use.
By implementing something like this on the platform specific layer would get around your current solution of re-downloading the image every single time.
Alternatively as a workaround, if you didn't want to implement the above, you could try putting two Image controls stacked upon each other, maybe in a Grid, with the bottom image showing a default placeholder image, and on-top another Image control that would show the intended image, if successfully downloaded, using the UriImageSource.
You could also possibly hook hook into the PropertyChange notification of the Image.Source and detect it being set, with the image then being displayed. Upon detection you could then release the image from the temporary place holder Image control perhaps?
In my application I'm saving an image and transferring to a server through the use of a php script whose sole job is to pass this image to the server which saves it in the root of the server.
The code I have for my upload is as follows:
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
UploadToServer.HttpUploadFile(Settings.Default.ServerAddress , sfd.FileName.ToString(), "file", "image/jpeg", nvc);
Settings.Default.ServerAddress holds the location of my upload php script which the following:
http://server.foo.com/images/upload.php
I have another php script that returns a string of all the file and folders held on my server that is returned and displayed in a text box.
I'm calling this like so:
using (var client = new WebClient())
{
result = client.DownloadString("http://server.foo.com/images/getDirectoryList.php");
}
What I need to do is have a way so that I can choose the location of where the my image is stored. My feeling is telling that I need to do is have a way so that when a user selects anything with .folder, the old string list disappears and the images and files is stored within that folder.
I believe the call I need to make is something like this:
http://server.foo.com/images/getDirectoyList.php?dir=test_folder
But I'm stuck on trying to implement what I want. For one, the list I get back is all highlight and say I get something like
Image 1
Image 2
Test_folder.folder
I have no way of being able to simply click on Image 2 and have it highlight the whole thing. Instead is simply places the cursor where I clicked. Likewise I have no idea of how I would pass this information over to the my upload code so that my chosen directory is used to store the image as opposed to the root.
Has anyone ever attempted something like this before?
Do you have any links or advice that could help me achieve what it is I want to achieve?
Additionally, but not important, would I be able to ever create a new directory / folder on my server through my C# winform application without having to touch either the php scripts or the server itself?
I'm so stuck on something i thought would be easy.
I have a DLL that returns an Image object.
I just cant figure out how to display that image on a webpage.
I've tried a few ways, and google a million different variations.
Is it not possible to just bind an Image object to an element on the page like an HtmlImage or a simple img?
Or do i need to convert the Image to a Stream? or a Bitmap? I'm really stuck!
Any help appreciated.....
V
With Asp.Net WebForm, the easiest way is to create a custom ashx file.
In Visual Studio, create a new Custom Handler (I'm not sure of the name of the template in Visual Studio). This will create a .ashx file.
In the code of this handler, write something like (does not have VS under the hand to test the syntax) :
public void ProcessRequest(System.Web.HttpContext context)
{
byte[] raw;
using(var ms = new MemoryStream()){
Image myImage = GetFromDll();
myImage.Save(ms, ImageFormat.Png);
raw=ms.ToArray();
}
context.Response.ContentType = "image/png";
context.Response.BinaryWrite(raw);
}
Then, in your browser, navigate to http://yourserver/app/yourhandler.ashx.
You can if you want add url parameter, and get it from the Request.QueryString collection
It's not as simple as binding. On the client side images are retrieved from the web server as a separate GET request, which means you have to have a URL that resolves to an image. The other option, as Asif suggested, is embedding your image in the HTML as a Base64 string, which is bad practice for shared images (see Steve B's comment).
You either have to provide an URL (route that returns the image file in MVC, or a custom page with proper content type and Response.Write in WebForms), or embed in html.
EDIT:
There is also a third option involving custom HTTP handlers. These have the advantage of bypassing the app framework and serving the content almost directly off the web server, see MSDN.
Convert your image to base64 string and then set it in the <img/> tag.
<img/> can show the image in base64 string.
Alternatively you can save the image and use the path in the <img/>.