Hi,
i use the FileManager v 22.2.7 with .Net 7.x in VS2022 and the SQLFileProvider; so all files are stored as varbinary(max) in a table on the server. This is all running pefect (after some work since i must extremly extend the structure; for multiple areas, users, filters, ...).
I now want to use the Pdf-Viewer, so that a user can 'open' a Pdf-file, make some annotations and store the changed file on the table. I know that i must handle the 'load' of the bytes on my own, since the 'content' is not part of the filemanager CWD (current working directory) or the 'files-array'.
So what is the best way, to load the data in the Pdf-viewer and save the changed version back?
Any sample available?
I think the same way is also useful for Document- and Image-Editor, or?
thanks for your support!
Patric
Hi Patric,
Greetings from Syncfusion support.
We have reviewed your query and understand that you are looking to preview the PDF file within the File Manager component. To achieve the PDF preview functionality we have to utilize the PDF Viewer component inside the Dialog component.
Refer to the below code snippet for further reference.
|
[Index.razor]
@using System.Text @using Microsoft.AspNetCore.Mvc; @using Syncfusion.Blazor.Popups @using Syncfusion.Blazor.PdfViewerServer @using System.Data.SqlClient;
<SfFileManager TValue="FileManagerDirectoryContent" AllowDragAndDrop="true" AllowMultiSelection="true"> .....
<FileManagerEvents TValue="FileManagerDirectoryContent" OnFileOpen="fileOpen"></FileManagerEvents> </SfFileManager>
<SfDialog @ref="dialog" Width="1200px" AllowPrerender="true" ShowCloseIcon="true" IsModal="true" Visible="false" Header="PDF Viewer"> <DialogTemplates> <Content> <SfPdfViewerServer @ref="PdfViewer" Width="1180px" Height="500px" /> </Content> </DialogTemplates> </SfDialog>
@code{
SfFileManager<FileManagerDirectoryContent> file; public SfPdfViewerServer PdfViewer; SfDialog dialog; public async Task fileOpen(Syncfusion.Blazor.FileManager.FileOpenEventArgs<FileManagerDirectoryContent> args) { if ((args.FileDetails.IsFile == true) && args.FileDetails.Type == ".pdf") { // Shows the PDF Viewer dialog await dialog.ShowAsync(); // Connection string to the SQL Server database string connectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\\New folder\\New\\Support\\November\\Blazor- FileManager-SQL_Provider\\BlazorApp1\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30"; System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString); // SQL query to retrieve the PDF content from the database based on the file name string query = "select Content from Product where Name = '" + args.FileDetails.Name + "'"; System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection); // Opens the database connection connection.Open(); FileStreamResult fileStreamResult = null; byte[] array; // Executes the SQL query and reads the PDF content using (SqlDataReader myReader = command.ExecuteReader()) { while (myReader.Read()) { try { // Creates a FileStreamResult from the retrieved PDF content fileStreamResult = new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/pdf"); } catch (Exception ex) { throw ex; } } }
// Copies the FileStreamResult content to a MemoryStream using (MemoryStream memoryStream = new MemoryStream()) { fileStreamResult.FileStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } // Constructs the data URL for the PDF Viewer var value = "data:application/pdf;base64," + Convert.ToBase64String(array); // Loads the PDF content into the PdfViewer await PdfViewer.LoadAsync(value); } } } |
We have also attached a sample for your reference.
Sample : Attached as zip folder.
Please get back to us if you need any further assistance.
Regards,
Suresh.
Hi Suresh,
thanks for your example (that i allready know), but i use a asp.net- or server hosted WASM; so my WASM must talk to the SqlFileProvider on the Server! My idea was to use the available Controler of the your File Manager!
My workflow / idea:
I insert a new route in the Controller and use the SQLGetImage route as pattern.
// Gets the file from the given ID
[Route("OpenFile")]
public IActionResult OpenFile(string F_ID)
{
//return operation.GetImage(args.Path, args.ParentID, args.Id, true, null, args.Data);
return operation.OpenFile(F_ID);
}
operation is from type SQLFileProvider; so the implementation of OpenFile(F_ID) is in SQLFileProvider
public FileStreamResult OpenFile(string s_F_ID)
{
try
{
/* is not used!!
AccessPermission permission = GetFilePermission(id, parentId, path);
if (permission != null && !permission.Read)
{
return null;
}
*/
sqlConnection = setSQLDBConnection();
sqlConnection.Open();
SqlCommand myCommand = new SqlCommand("select Content from " + tableName + " where ItemID =" + s_F_ID, sqlConnection);
SqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
try
{
return new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/octet-stream"); ;
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
}
sqlConnection.Close();
return null;
}
catch (Exception)
{
return null;
}
}
My FileManger looks like this
<SfFileManager TValue="Server.Models.Base.FileManagerDirectoryContent" ShowThumbnail="true" AllowDragAndDrop="true" AllowMultiSelection="false" @ref="filemanager">
<FileManagerAjaxSettings Url=@sakt_Url
UploadUrl=@sakt_Upload
DownloadUrl="/api/SQLProvider/SQLDownload"
GetImageUrl="/api/SQLProvider/SQLGetImage">
</FileManagerAjaxSettings>
<FileManagerDetailsViewSettings>
<FileManagerColumns>
<FileManagerColumn Field="Name" HeaderText="Name"></FileManagerColumn>
<FileManagerColumn Field="DateCreated" Format="dd.MM.yyyy h:mm tt" HeaderText="Erstellt"></FileManagerColumn>
<FileManagerColumn Field="DateModified" Format="dd.MM.yyyy h:mm tt" HeaderText="Geändert"></FileManagerColumn>
<FileManagerColumn Field="Size" HeaderText="Größe"></FileManagerColumn>
<FileManagerColumn Field="Typ" HeaderText="Typ"></FileManagerColumn>
</FileManagerColumns>
</FileManagerDetailsViewSettings>
<FileManagerContextMenuSettings File="@CItems" Folder="@Items"></FileManagerContextMenuSettings>
<FileManagerToolbarSettings ToolbarItems="@TItems"></FileManagerToolbarSettings>
<FileManagerEvents TValue="Server.Models.Base.FileManagerDirectoryContent" OnFileOpen="OpenFilePreview" OnSend="OnSend"></FileManagerEvents>
<FileManagerUploadSettings MaxFileSize="52000000 "></FileManagerUploadSettings>
</SfFileManager>
My code behind (FileManager.razor.cs) is
private void OpenFilePreview(FileOpenEventArgs<Server.Models.Base.FileManagerDirectoryContent> args)
{
if (args.FileDetails.IsFile)
{
string sFType = args.FileDetails.Type;
string[] sWord = { ".doc", ".docx", ".docb" };
if (sFType == ".pdf")
{
LookupService.sakt_Datei = args.FileDetails.Path;
LookupService.iakt_Datei = int.Parse(args.FileDetails.Id);
sakt_F_ID = args.FileDetails.Id;
Lade_Datei();
// Lade die Datei
// Öffne den PDF-Viewer
DialogService.Open<FilePDF_New>("Vorschau der PDF-Datei: " + args.FileDetails.Name, null, new DialogOptions() { Width = "1024px", Height = "800px", Resizable = true, Draggable = true });
}
else if (sWord.Any(sFType.Contains))
{
LookupService.sakt_Datei = args.FileDetails.Path;
LookupService.iakt_Datei = int.Parse(args.FileDetails.Id);
sakt_F_ID = args.FileDetails.Id;
Lade_Datei();
DialogService.Open<FileWord>("Vorschau der Word-Datei: " + args.FileDetails.Name, null, new DialogOptions() { Width = "1024px", Height = "800px", Resizable = true, Draggable = true });
}
else
{
DialogService.Alert("Vorschau der Datei: " + args.FileDetails.Name + " ist nicht möglich! Nur Word- und PDF-Dateien können bearbeitet werden!", "Kein 'Öffnen' möglich! Nur 'Download'!");
LookupService.sakt_Datei = "";
}
}
}
public void Lade_Datei()
{
if (sakt_F_ID != "0")
{
string saktUrl1 = NavigationManager.BaseUri + "api/SQLProvider/OpenFile?F_ID=" + sakt_F_ID;
byte[] byteArray = System.IO.File.ReadAllBytes(saktUrl1);
string base64String = Convert.ToBase64String(byteArray);
// LookupService is a 'State Service where i store global values like public FileStream akt_F_Stream or
// public string sakt_F_String;
LookupService.sakt_F_String = "data:apple64," + Convert.ToBase64String(byteArray);
// check the first selected file in the File Manager; not realy necessary
var Test = filemanager.GetSelectedFiles().FirstOrDefault();
string[] sArrFile = { Test.Name };
this.filemanager.DownloadFilesAsync(filemanager.SelectedItems);
var fTest = this.filemanager.OpenFileAsync(filemanager.SelectedItems[0].ToString());
}
}
I try to use the OpenFile route and store the result as local Base64String (= LookupService.sakt_F_String) and use this as File for the PDF-Viewer (DocumentPath = LookupService.sakt_F_String;). But if i trace in the running code, i see that no bytes are loaded from System.IO.File.ReadAllBytes(saktUrl1);
Next I try to Download the file manually to a variable fTest; but this also not working.
Any hint or idea how to solve my problem or do you have an example where you download a file via FileManager and open this file with the PDF Viewer (best with the new one)?
Thanks for help
Patric
Hi Patric,
Based on the shared details, we have understand that you are using Blazor WASM File Manager sample integrated with SQL File Provider. We have prepared sample to achieve your requirement and shared it for your reference.
Refer to the below code snippet for further reference.
|
[Index.razor]
<SfFileManager TValue="FileManagerDirectoryContent" AllowDragAndDrop="true" AllowMultiSelection="true"> .....
<FileManagerEvents TValue="FileManagerDirectoryContent" OnFileOpen="fileOpen"></FileManagerEvents> </SfFileManager>
<SfDialog @ref="dialog" Width="1200px" AllowPrerender="true" ShowCloseIcon="true" IsModal="true" Visible="false" Header="PDF Viewer"> <DialogTemplates> <Content> <SfPdfViewer2 @ref="PdfViewer" Height="100%" Width="100%"></SfPdfViewer2> </Content> </DialogTemplates> </SfDialog>
@code{
SfFileManager<FileManagerDirectoryContent> file; public SfPdfViewer2 PdfViewer; SfDialog dialog; private HttpClient httpClient;
public async Task fileOpen(Syncfusion.Blazor.FileManager.FileOpenEventArgs<FileManagerDirectoryContent> args) { if ((args.FileDetails.IsFile == true) && args.FileDetails.Type == ".pdf") { // Shows the PDF Viewer dialog await dialog.ShowAsync(); httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(args.FileDetails.Id); var responseData = await httpClient.GetStringAsync(https://localhost:7121/api/SQLProvider/SQLFilePreview); await PdfViewer.LoadAsync(responseData); } } }
|
|
[SQLProviderController.cs]
[Route("SQLFilePreview")] public IActionResult SQLFilePreview(FileManagerDirectoryContent args) { // Fetch the file id value var fileId = HttpContext.Request.Headers["Authorization"]; string name = "EJ2 File Manager.pdf"; // Connection string to the SQL Server database string connectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\\New folder\\New\\Support\\November\\FileManager-WASM-SQLProvider\\BlazorApp1\\Server\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30"; System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString); // SQL query to retrieve the PDF content from the database based on the file name string query = "select Content from Product where ItemID = '" + fileId[0] + "'"; System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection); // Opens the database connection connection.Open(); FileStreamResult fileStreamResult = null; byte[] array; // Executes the SQL query and reads the PDF content using (SqlDataReader myReader = command.ExecuteReader()) { while (myReader.Read()) { try { // Creates a FileStreamResult from the retrieved PDF content fileStreamResult = new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/pdf"); } catch (Exception ex) { throw ex; } } }
// Copies the FileStreamResult content to a MemoryStream using (MemoryStream memoryStream = new MemoryStream()) { fileStreamResult.FileStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } // Constructs the data URL for the PDF Viewer var value = "data:application/pdf;base64," + Convert.ToBase64String(array); return Ok(value); } |
We have attached a sample for your reference.
Sample : Attached as zip folder.
Furthermore, While examining your implementation and reviewed the shared query, we observed that you are utilizing the "DownloadFilesAsync" method and "OpenFileAsync" method to download and open PDF files. However, It is important to note that the "OpenFileAsync" method is scoped within the File Manager component, and it cannot be used to open downloaded PDF files from File Explorer.
To address your requirement for downloading files within the File Manager component, we recommend checking out the details in our forum discussion.
Forum : https://www.syncfusion.com/forums/166666/opening-files-in-file-manager?reply=SEAHYJ
Check out the shared details and get back to us if you need any further assistance.
Regards,
Suresh.
Hi Suresh,
sorry for my late reply; had some project stress.
Thanks for your example; it works in my project with some modification:
string sBase_Adress;
protected override async Task OnInitializedAsync()
{
sBase_Adress = NavigationManager.BaseUri;
}
and then i use
var responseData = await httpClient.GetStringAsync(sBase_Adress + "api/SQLProvider/SQLFilePreview");
[Route("SQLFilePreview")]
public IActionResult SQLFilePreview(FileManagerDirectoryContent args)
{
// Fetch the file id value
var fileId = HttpContext.Request.Headers["Authorization"];
// string name = "File Manager.pdf"; --> Is never used!
// Connection string to the SQL Server database
string connectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\\New folder\\New\\Support\\November\\FileManager-WASM-SQLProvider\\BlazorApp1\\Server\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30";
// SQL query to retrieve the PDF content from the database based on the file name
//string query = "select Content from Folder_Files where ItemID = '" + fileId[0] + "'";
string query = "select MimeType, Content from Folder_Files where ItemID = '" + fileId[0] + "'";
Microsoft.Data.SqlClient.SqlCommand command = new Microsoft.Data.SqlClient.SqlCommand(query, connection);
string sMimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
// Opens the database connection
connection.Open();
FileStreamResult fileStreamResult = null;
byte[] array;
// Executes the SQL query and reads the PDF content
using (SqlDataReader myReader = command.ExecuteReader())
{
while (myReader.Read())
{
try
{
sMimeType = myReader["MimeType"].ToString();
// Creates a FileStreamResult from the retrieved PDF content
//fileStreamResult = new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/pdf");
fileStreamResult = new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), sMimeType);
}
catch (Exception ex) { throw ex; }
}
}
// Copies the FileStreamResult content to a MemoryStream
using (MemoryStream memoryStream = new MemoryStream())
{
fileStreamResult.FileStream.CopyTo(memoryStream);
array = memoryStream.ToArray();
}
// Constructs the data URL for the PDF Viewer
// var value = "data:application/pdf;base64," + Convert.ToBase64String(array);
var value = "data:" + sMimeType + ";base64," + Convert.ToBase64String(array);
return Ok(value);
}
Thanks for your help!
But i have an additional question:
In the 'OpenFilePreview-Event' i can detect theFileDetails.Type. If .pdf i open the dialog with the pdf-viewer. On the same way i can detect word documents and images. So how can i use the Controler to load a Word Document in the DocumentEditor or an image in the ImageEditor? Or should i create a controler for each type?
And since i can change the files in your editors, how can i save/update the changed files in the database? Any example will be great.
Thanks in advance.
Patric
Hi Suresh,
unfortunaly your solution with my little add on works only in my dev environment!
If i deploy to a real root server in the internet i get an error!
The Controller with the function 'SQLFilePreview' is called and the PDF-Viewer opens. But then the Spinner turns and turns and nothing happens. If i hit F12 in Edge-Browser, i see there is an error in a JavaScript function say:
'ncaught TypeError: i.Init is not a function
at h.onmessage (859ce19e-7f23-4898-877b-f3349adc43ae:1:3165)'
Don't know if this says anything to you; any idea what went wrong?
Thanks for help.
Patric
Hi Patric,
We have reviewed your query and understand that you have two requirements and one concerns in the File Manager component. We suggest you to follow the below details to get answer for your queries.
Query 1 : Looking to preview the document file through DocumentEditor.
To achieve this requirement we have to utilize the DocumentEditor component. Refer to the below code snippet for further reference.
|
[Index.razor]
<SfDialog @ref="documentDialog" Width="1200px" AllowPrerender="true" ShowCloseIcon="true" IsModal="true" Visible="false" Header="Image Editor"> <DialogTemplates> <Content> <SfDocumentEditorContainer @ref="documentEditor" Height="600px" Width="100%"></SfDocumentEditorContainer> </Content> </DialogTemplates> <DialogEvents Opened="OnOpened"></DialogEvents> </SfDialog>
....
@code { SfFileManager<FileManagerDirectoryContent> file; public SfPdfViewer2 PdfViewer; SfDialog dialog; SfDialog imageDialog; SfDialog documentDialog; SfImageEditor imageEditor; SfDocumentEditorContainer documentEditor; byte[] array; private HttpClient httpClient;
async Task OnOpened() { await documentEditor.ResizeAsync(); await documentEditor.DocumentEditor.ResizeAsync(); }
public async Task fileOpen(Syncfusion.Blazor.FileManager.FileOpenEventArgs<FileManagerDirectoryContent> args) { ....
else if (args.FileDetails.IsFile == true && args.FileDetails.Type == ".docx") { // Shows the PDF Viewer dialog await documentDialog.ShowAsync(); httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(args.FileDetails.Id); var responseData = await httpClient.GetStreamAsync(https://localhost:7121/api/SQLProvider/SQLDocumentFilePreview); WordDocument document = WordDocument.Load(responseData, ImportFormatType.Docx); responseData.Dispose(); //To observe the memory go down, null out the reference of stream variable. responseData = null; string json = JsonSerializer.Serialize(document); document.Dispose(); //To observe the memory go down, null out the reference of document variable. document = null; SfDocumentEditor editor = documentEditor.DocumentEditor; await editor.OpenAsync(json); } } } |
|
[SQLProviderController.cs]
[Route("SQLDocumentFilePreview")] public IActionResult SQLDocumentFilePreview(FileManagerDirectoryContent args) { // Fetch the file id value var fileId = HttpContext.Request.Headers["Authorization"]; string name = "EJ2 File Manager.docx"; // Connection string to the SQL Server database string connectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\\New folder\\New\\Support\\November\\FileManager-WASM-SQLProvider\\BlazorApp1\\Server\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30"; System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString); // SQL query to retrieve the PDF content from the database based on the file name string query = "select Content from Product where ItemID = '" + fileId[0] + "'"; System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection); // Opens the database connection connection.Open(); SqlDataReader read = command.ExecuteReader(); read.Read(); //Reads the Word document data as byte array from the database byte[] byteArray = (byte[])read["Content"]; Stream stream = new MemoryStream(byteArray); //To observe the memory go down, null out the reference of byteArray variable. byteArray = null; return Ok(stream); } |
Query 2 : Looking to preview the image file through ImageEditor.
To achieve this requirement we have to utilize the ImageEditor component. Refer to the below code snippet for further reference.
|
[Index.razor]
<SfDialog @ref="imageDialog" Width="1200px" AllowPrerender="true" ShowCloseIcon="true" IsModal="true" Visible="false" Header="Image Editor"> <DialogTemplates> <Content> <SfImageEditor @ref="imageEditor" Height="400px"></SfImageEditor> </Content> </DialogTemplates> </SfDialog>
.....
@code { SfFileManager<FileManagerDirectoryContent> file; public SfPdfViewer2 PdfViewer; SfDialog dialog; SfDialog imageDialog; SfDialog documentDialog; SfImageEditor imageEditor; SfDocumentEditorContainer documentEditor; byte[] array; private HttpClient httpClient; ....
public async Task fileOpen(Syncfusion.Blazor.FileManager.FileOpenEventArgs<FileManagerDirectoryContent> args) { ....
else if (args.FileDetails.IsFile == true && args.FileDetails.Type == ".jpg") { args.Cancel = true; await imageDialog.ShowAsync(); httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(args.FileDetails.Id); var responseData = await httpClient.GetStringAsync(https://localhost:7121/api/SQLProvider/SQLImageFilePreview); await imageEditor.OpenAsync(responseData); } .... } } |
|
[SQLProviderController.cs]
[Route("SQLImageFilePreview")] public IActionResult SQLImageFilePreview(FileManagerDirectoryContent args) { // Fetch the file id value var fileId = HttpContext.Request.Headers["Authorization"]; string name = "sea.jpg"; // Connection string to the SQL Server database string connectionString = "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=D:\\New folder\\New\\Support\\November\\FileManager-WASM-SQLProvider\\BlazorApp1\\Server\\App_Data\\FileManager.mdf;Integrated Security=True;Connect Timeout=30"; System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString); // SQL query to retrieve the PDF content from the database based on the file name string query = "select Content from Product where ItemID = '" + fileId[0] + "'"; System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(query, connection); // Opens the database connection connection.Open(); FileStreamResult fileStreamResult = null; byte[] array; // Executes the SQL query and reads the PDF content using (SqlDataReader myReader = command.ExecuteReader()) { while (myReader.Read()) { try { // Creates a FileStreamResult from the retrieved PDF content fileStreamResult = new FileStreamResult(new MemoryStream((byte[])myReader["Content"]), "APPLICATION/jpg"); } catch (Exception ex) { throw ex; } } }
// Copies the FileStreamResult content to a MemoryStream using (MemoryStream memoryStream = new MemoryStream()) { fileStreamResult.FileStream.CopyTo(memoryStream); array = memoryStream.ToArray(); } // Constructs the data URL for the PDF Viewer var value = "data:image/png;base64," + Convert.ToBase64String(array); return Ok(value); } |
We have attached a sample for your reference.
Sample : Attached as zip folder.
Query 3 : When deploying the application in live server, opening a PDF in a viewer, the spinner keeps on loading without displaying the content, also it throws error in console.
We would like to inform you that currently we are checking the reported issue with the corresponding team. We need some additional time and we will update you with further details by December 14, 2023.
Regards,
Suresh.
Hi Patric,
Query : When deploying the application in live server, opening a PDF in a viewer, the spinner keeps on loading without displaying the content, also it throws error in console.
For this query we requested you to share the below details with us.
These details will help us to validate your query further and provide you with a prompt solution.
Regards,
Suresh.