Closed bjarnef closed 2 years ago
@ronaldbarendse do you know this should work on Umbraco Cloud, which by default use blob storage?
would it use the implementation of GetFullPath()
here?
https://github.com/umbraco/Umbraco.StorageProviders/blob/main/src/Umbraco.StorageProviders.AzureBlob/IO/AzureBlobFileSystem.cs#L209-L216
@bjarnef The GetFullPath()
method is indeed a bit weird, as Azure Blob Storage (used on Umbraco Cloud) can't return a full path to the file, only an absolute URL. Because FileExists()
and OpenFile()
only require the relative path, I would recommend removing the call or change it to GetRelativePath()
instead.
@ronaldbarendse I changed to the following instead:
string path = _ioHelper.GetRelativePath(File);
_logger.LogInformation("Full path {Path}", path);
if (_mediaFileManager.FileSystem.FileExists(path))
{
var stream = _mediaFileManager.FileSystem.OpenFile(path);
stream.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(stream))
{
var svg = sr.ReadToEnd();
if (!string.IsNullOrEmpty(svg))
{
output.Content.SetHtmlContent(svg);
}
}
}
but it doesn't seem to render SVG icon locally or on Umbraco Cloud.
On Umbraco Cloud the path is logged as ~/media/rybamegd/document.svg
which looks similar to the path format here: https://our.umbraco.com/documentation/Reference/V9-Config/filesystemProviders#get-the-contents-of-a-file-as-a-stream
Because FileExists() and OpenFile() only require the relative path
It would be great it the methods had a comment about this as it currently not is easy to know which format the path should be.
Okay, so if I trim ~
from path it works:
using Umbraco.Extensions;
...
string path = _ioHelper.GetRelativePath(File);
path = path.TrimStart("~")
_logger.LogInformation("Full path {Path}", path);
if (_mediaFileManager.FileSystem.FileExists(path))
{
var stream = _mediaFileManager.FileSystem.OpenFile(path);
stream.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(stream))
{
var svg = sr.ReadToEnd();
if (!string.IsNullOrEmpty(svg))
{
output.Content.SetHtmlContent(svg);
}
}
}
Instead of including Umbraco.Extensions
namespace, it is also possible to use this instead:
string path = _ioHelper.GetRelativePath(File);
path = path.TrimStart(Umbraco.Cms.Core.Constants.CharArrays.Tilde);
Mixing virtual paths (starting with ~/
) and physical file paths doesn't make much sense in ASP.NET Core, as the web root is abstracted as an IFileProvider
you can access from IWebHostEnvironment.WebRootFileProvider
. You can also use IHostEnvironment.ContentRootFileProvider
to get application content files that aren't publicly served...
Umbraco's IFileSystem
is a separate thing, as it also includes write support, so I would suggest rewriting your tag helper to either use this or the IFileProvider
... I'm experimenting on trying to combine these two concepts in PR https://github.com/umbraco/Umbraco.StorageProviders/pull/11.
@ronaldbarendse in this case I could just use value of File
property but _ioHelper.GetRelativePath(File)
would return relative URL in case I pass in absolute URL.
IFileSystem
is actual what I already use via _mediaFileManager.FileSystem
.
I haven't checked IFileProvider
though, but a quick glance at source in GitHub repository it seems the only reference is here: https://github.com/umbraco/Umbraco-CMS/blob/v9/contrib/src/Umbraco.Web.Common/Plugins/UmbracoPluginPhysicalFileProvider.cs#L19
namespace MyProject.Core.TagHelpers
{
using System;
using System.IO;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.IO;
using Constants = Umbraco.Cms.Core.Constants;
[HtmlTargetElement("svg-icon", TagStructure = TagStructure.NormalOrSelfClosing)]
public class SvgIconTagHelper : TagHelper
{
private readonly IIOHelper _ioHelper;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly MediaFileManager _mediaFileManager;
private readonly ILogger<SvgIconTagHelper> _logger;
public SvgIconTagHelper(
IIOHelper ioHelper,
IHostingEnvironment hostingEnvironment,
MediaFileManager mediaFileManager,
ILogger<SvgIconTagHelper> logger)
{
_ioHelper = ioHelper;
_hostingEnvironment = hostingEnvironment;
_mediaFileManager = mediaFileManager;
_logger = logger;
}
/// <summary>
/// Path to SVG file
/// </summary>
public string File { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (string.IsNullOrWhiteSpace(File))
{
throw new ArgumentNullException(nameof(File));
}
output.TagName = "span";
var classAttribute = output.Attributes["class"];
var classes = (classAttribute?.Value as HtmlString)?.Value ?? string.Empty;
classes += " icon";
classes = classes.Trim();
output.Attributes.SetAttribute("class", classes);
output.TagMode = TagMode.StartTagAndEndTag;
try
{
string path = _ioHelper.GetRelativePath(File);
path = path.TrimStart(Constants.CharArrays.Tilde);
if (_mediaFileManager.FileSystem.FileExists(path))
{
var stream = _mediaFileManager.FileSystem.OpenFile(path);
stream.Seek(0, SeekOrigin.Begin);
using (StreamReader sr = new StreamReader(stream))
{
var svg = sr.ReadToEnd();
if (!string.IsNullOrEmpty(svg))
{
output.Content.SetHtmlContent(svg);
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed reading SVG icon");
}
}
}
}
Hiya @bjarnef,
Just wanted to let you know that we noticed that this issue got a bit stale and might not be relevant any more.
We will close this issue for now but we're happy to open it up again if you think it's still relevant (for example: it's a feature request that's not yet implemented, or it's a bug that's not yet been fixed).
To open it this issue up again, you can write @umbrabot still relevant
in a new comment as the first line. It would be super helpful for us if on the next line you could let us know why you think it's still relevant.
For example:
@umbrabot still relevant This bug can still be reproduced in version
x.y.z
This will reopen the issue in the next few hours.
Thanks, from your friendly Umbraco GitHub bot :robot: :slightly_smiling_face:
Which exact Umbraco version are you using? For example: 8.13.1 - don't just write v8
9.0.1
Bug summary
I have a custom Tag Helper where I inject
MediaFileManager
. From this I can also accessIFileSystem
via theFileSystem
property.Here is an example, where
File
is a relative path returned frommediaItem.Url()
:Locally this works an
GetFullPath()
returnsC:\VSProjects\my-project\UmbracoCloud\src\UmbracoProject\wwwroot\media\rybamegd\document.svg
and render the SVG Icon.However on Umbraco Cloud is log this path from
GetFullPath()
: Full path "media/~/media/rybamegd/document.svg"I would have expected it to return an absolute path to the media file. Not sure if it's a core issue or maybe the implementation of GetFullPath() here? https://github.com/umbraco/Umbraco.StorageProviders/blob/main/src/Umbraco.StorageProviders.AzureBlob/IO/AzureBlobFileSystem.cs#L209-L216
The tag helper is used as the following:
Specifics
No response
Steps to reproduce
Inject
MediaFileManager
to a custom Tag Helper or just in view file for testing.Use the following to get the full path to the file.
Expected result / actual result
No response