Closed mreic closed 1 year ago
Stream is fully available on client side? Can you check if it works with a data url for the stream?
DataUrl.GetDataUrl(stream.ToByteArray())
That means in your case
using Nextended.Blazor.Models;
...
await dialogService.ShowFileDisplayDialog(DataUrl.GetDataUrl(stream.ToByteArray()), uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
What do you mean by "fully available on client side"? File is stored on the servers filesystem.
Testing as follows:
This test does not work. If you uncomment the bytes-assignment and the second dialog call and comment out the first dialog call you can open small files. Large files get an "URI too Long"-Exception.
I just tested a little further: If i try opening the dialog your suggested way, then opening images are working fine, but other types, like .pdf or .json files result in a immediate download which looks like this: Note, that the 0 Byte files in that download list have been produced while testing.
I wrote a little function myself like this:
Using this allows me to open any files that are not too large for the URI.
Ok understand. I also fixed stream handling but that doesnt help you at all. Because for native file display (That means without custom IMudExFileDisplay implementation like Zip or Markdown handling) also a is created from stream because depending on mimetype iframe, img tag or object tags are used and they need a url
if youre files came from server and I would have you problems I would ensure to have a url for the file itself. For example if you have your files in a database (or whatever) i would create a Controller to read the files. I mean like this
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class FileController : ControllerBase
{
private readonly IFileRepo _fileRepo;
public FileController(IFileRepo fileRepo)
{
_fileRepo = fileRepo;
}
[HttpGet("{id}")]
public IActionResult GetFileById(string id)
{
byte[] fileData = _fileRepo.GetFile(id);
if (fileData == null || fileData.Length == 0)
{
return NotFound();
}
return File(fileData, "application/octet-stream"); // Set the appropriate MIME type if you know it.
}
}
than you can use a url like api/file/123
Hope that helps a bit.
Thank you very much for sharing this bug, i fixed it and it will released in 1.7.68 you can have a look at preview package 1.7.68-prev-2309141720-main
also you can see it running here https://mudex.azurewebsites.net/handle-file-as-streams (all files here are set as stream see code)
Would you explain why you cant update MudBlazor to 6.9 ?
I'll test it tomorow.. Thank you in advance!
I cant Upgrade because of a Bug i reported in MudBlazor (https://github.com/MudBlazor/MudBlazor/issues/7237). I use exactly that combination of options in MudDataGrid and unfortunately nobody is responding at this time.. but we will see. I personally cant find a working workaround for this so i am Stuck with this Version for the moment.
I created a compatible package with MudBlazor 6.4.1 for you. Hope that helps. If it does please close this issue.
Thanks for the Package! It helps for mostly all use-cases. Mostly, because i experienced that larger PDF-Files are not loaded. They can be downloaded, but the preview pane keeps empty.
Any Idea on this?
Update: It seems that i can update my project to something above 6.4.1 because somebody posted a workarround. I need to do some testing to validate this.
While further testing it seems that the file display components dont dispose properly. May be that its my code doing sth wrong, but RAM-usage increases on every dialog call and stays up even when GC takes place.
Sorry for asking so many questions ;)
No problem your welcome.
For question 1: Pdf and all other native display files like image etc where tag is used needs an url, and maybe your pdf is to big for a data url. I guess you need to playaround with it, or if you can provide a sample pdf I will have a look if I can do something.
For question 2: Stream is currently not disposed on component side because I dont want to close given streams because this can cause side effects. (However for MudExFileDisplayZip they are copied and maybe I need to rethink about disposing given streams )
For your first answer: I once build a simple file preview (mostly only pdf and images) facing the nearly same problem with larger files. I found a way to do this using following function in "_host.cshtml" :
window.openFileFromStream = async (fileName, contentStreamReference, fileType) => {
const arrayBuffer = await contentStreamReference.arrayBuffer();
const blob = new Blob([arrayBuffer], { type: fileType });
const url = URL.createObjectURL(blob);
//document.querySelector("embed").src = url;
const elem = document.getElementById("preview-element");
if(elem != null){
elem.src = url;
await new Promise(resolve => setTimeout(resolve, 1000));
URL.revokeObjectURL(url);
}
else{
URL.revokeObjectURL(url);
}
}
I personally dont know if its a nearly clean idea to get rid of the file size issue. Maybe you can check?
Second answer: I am using this call:
string mimetype = Utilities.Utilities.GetMimeType(uploadedFile.uploaded_file_orig_file_name);
//await DialogService.ShowFileDisplayDialog($"https://localhost:1235/api/file/{uploadedFile.uploaded_file_id}", uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
using (Stream stream = GetFileStream(uploadedFile))
{
await DialogService.ShowFileDisplayDialog(stream, uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
}
Seeing the code i would expect the stream to get closed and als release resources. Is there any possibilities for your component to keep data that was read from stream?
Your stream should get disposed, but anyway I found a bug where copied streams are staying open. I currently work on a fix for that.
For point 1 it's a good idea to use object stores uri, I think I can change the behavior to work like this
Can you test this package? 1.7.68-prev-2309182049-stre...
You can now set url handling to blob the MudExFileDisplay has now a Parameter for that called StreamUrlHandling
If you use a dialog you can set it like this
private async Task OpenAsDialog()
{
var parameters = new DialogParameters {
{ nameof(MudExFileDisplay.StreamUrlHandling), StreamUrlHandling.BlobUrl }
};
await dialogService.ShowFileDisplayDialog(SampleFile.Stream, SampleFile.Name, SampleFile.ContentType, HandleContentError, null, parameters);
}
In this example its setup to use blob uris https://mudex.azurewebsites.net/handle-file-as-streams
Thank you for your always fast replies! Larger PDF work now! Unfortunatly .zip-files now are broken.
The error is the same on calling the Dialog without the parameters.
Unfortunatelly, the info also causes crashes on all files in my test-environment
That's strange my samples with zip and other archives working well will correct stream dispose. Can you provide a sample solution with your errors? Than I can have a look
What exactly do you want to see? I want to get it as precise as possible for you!
The zip and info bug reproducible should be enough. You have a server side rendered project? Maybe there is the difference. Because in my sample https://mudex.azurewebsites.net/handle-file-as-streams it works well
Yes, my project is rendered server side. I tried to open following zip: open3A 3.8.zip
Dialog starts showing the loading spinner while the debugger prints the error from the screenshot posted earlier ("Cannot access a closed stream)
Dialog call is exacly like you suggested:
Your code:
private async Task OpenAsDialog()
{
var parameters = new DialogParameters {
{ nameof(MudExFileDisplay.StreamUrlHandling), StreamUrlHandling.BlobUrl }
};
await dialogService.ShowFileDisplayDialog(SampleFile.Stream, SampleFile.Name, SampleFile.ContentType, HandleContentError, null, parameters);
}
My code:
private async Task OpenAsDialog(UploadedFileModel uploadedFile)
{
//DialogOptionsEx options = new DialogOptionsEx() { JsRuntime = JS};
//Stream stream = null;
try
{
string mimetype = Utilities.Utilities.GetMimeType(uploadedFile.uploaded_file_orig_file_name);
//await DialogService.ShowFileDisplayDialog($"https://localhost:1235/api/file/{uploadedFile.uploaded_file_id}", uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
var parameters = new DialogParameters {
{ nameof(MudExFileDisplay.StreamUrlHandling), StreamUrlHandling.BlobUrl }
};
using (Stream stream = GetFileStream(uploadedFile))
{
await DialogService.ShowFileDisplayDialog(stream, uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS, parameters);
//await DialogService.ShowFileDisplayDialog(stream, uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
}
}
catch(Exception e)
{
Console.Write(e.ToString());
}
}
Hope this helps ;)
Sorry for Late answering today i was not at home. I see your problem. Your scope is finished to early because you are await the show of the dialog only what returns a IDialogReference from MudBlazor if you want to await the closeing to ensure dispose afterwards you need to await the result of the IDialogRefeference
using (var stream = SampleFile.Stream) {
var res = await dialogService.ShowFileDisplayDialog(stream, SampleFile.Name, SampleFile.ContentType, HandleContentError, null, parameters);
await res.Result;
}
Thanks for the Explanation! Seems like everything is working right now.
Contact Details
No response
What happened?
I have a Blazor Server with a upload folder where files are uploaded. If i want to display one of these files from stream using the following command:
await DialogService.ShowFileDisplayDialog(stream, uploadedFile.uploaded_file_orig_file_name, mimetype, HandleContentError, ex => ex.JsRuntime = JS);
the display control shows as follows:
I checked if the stream is available, which it is.
Unfortunately i cannot use the newest version of MudEx because of a bug in MudBlazor since 6.5.
Expected Behavior
The file should be displayed.
Screenshots
No response
What application type are you referring to?
Other
Custom Application Type
Server
MudBlazor.Extension Version
1.7.61
MudBlazor Version
6.4.1
What browser are you using?
Chrome
Sample Solution
No response
Pull Request
No response
Code of Conduct