Trying to set the source of an IMG container in a Blazor server-side page (internally accessible only) to a picture stored on a file share server, is giving me the error: not allowed to load local resource. Disabling the chrome security is not an option.
In the old web-forms version, the modal pop-up had the source set to a separate page that opened the image full page with the following code:
if (!string.IsNullOrEmpty(Request.QueryString["pic"]))
{
string path = Request.QueryString["pic"];
string file = Request.QueryString["fp"];
byte[] Content = File.ReadAllBytes(path);
if (file.ToUpper().Contains("PDF"))
{
Response.ContentType = "application/pdf";
}
else if (file.ToUpper().Contains("JPG") || file.ToUpper().Contains("JPEG") || file.ToUpper().Contains("PNG"))
{
Response.ContentType = "image/jpeg";
}
else if (file.ToUpper().Contains("PNG"))
{
Response.ContentType = "image/png";
}
else
{
Response.ContentType = "application/msword";
}
Response.AddHeader("content-disposition", "inline; filename=" file);
Response.BufferOutput = true;
Response.OutputStream.Write(Content, 0, Content.Length);
Response.End();
}
And, for the modal pop-up, the file share server path and file name were added via query string:
MPE.PopupControlID = "pic";
MPE.CancelControlID = "btnClosePic";
MPE.Show();
iFramePictures.Attributes.Add("src", "LoadImage.aspx?pic=" attachmentPath "&fp=" filename);
So it was then displayed in the modal pop-up like this:
What's the best practice way to load a file that was uploaded to a FS server as that image source? I can copy the files from a folder on that server to another destination, but can't seem to get the file to be assigned as the source for the container. Is there a way to use a memorystream as the source?
CodePudding user response:
I tried display the local image as below:
<img src="data:image/gif;base64,@Convert.ToBase64String(File.ReadAllBytes("wwwroot/img/5.4.test.gif"))">
picture from File Share Server:
@inject HttpClient Httpclient
<img src="data:image/gif;base64,@Convert.ToBase64String(Httpclient.GetByteArrayAsync("https://avatars.githubusercontent.com/u/9141961").Result)">
in program.cs:
builder.Services.AddHttpClient();
The Result: the offcial document related:
https://docs.microsoft.com/en-us/aspnet/core/blazor/images?view=aspnetcore-6.0
CodePudding user response:
You could use a action method in a controller:
public class ImageController : Controller
{
public IActionResult LoadImage(string pic, string fp)
{
if (string.IsNullOrEmpty(pic))
return NotFound();
if (string.IsNullOrEmpty(fp))
return NotFound();
string contentType;
if (fp.ToUpper().Contains("PDF"))
{
contentType = "application/pdf";
}
else if (fp.ToUpper().Contains("JPG") || fp.ToUpper().Contains("JPEG") || fp.ToUpper().Contains("PNG"))
{
contentType = "image/jpeg";
}
else if (fp.ToUpper().Contains("PNG"))
{
contentType = "image/png";
}
else
{
contentType = "application/msword";
}
return PhysicalFile(fp, contentType);
}
}
Lots of ways to generate the URL, but you could just: @Url.Action("LoadImage", "Image")
Getting started with Controllers and Actions.
CodePudding user response:
In startup.cs:
endpoints.MapControllers();
Per mxmissle's recommendation, controller added to the project:
using Microsoft.AspNetCore.Mvc;
using System.IO;
[Route("api/[controller]")]
[ApiController]
public class Images : ControllerBase
{
[HttpGet("[action]")]
public IActionResult DownloadPicture(string filePath)
{
var stream = new FileStream(filePath, FileMode.Open);
var result = new FileStreamResult(stream, "image/png");
result.FileDownloadName = "Picture";
return result;
}
}
And, on the page:
<img src="@Source"> (style it however you want)
And, in the button click, I just needed (Images (in the assignment of the Source variable) was the name of the controller):
Source = "/api/Images/DownloadPicture?filepath=<File Path Here>";