This is a migrated thread and some comments may be shown as answers.

Problem Exporting Content with Image to DOCX

2 Answers 281 Views
Editor
This is a migrated thread and some comments may be shown as answers.
Luiz
Top achievements
Rank 1
Luiz asked on 26 Mar 2015, 03:03 AM
HI, i'm experiencing some difficulties on export content from radeditor (with images) to docx format, using radeditor.exportToDocX() method.

the problem is:
An exception of type 'Telerik.Web.UI.Editor.Export.RadEditorExportException' occurred in Telerik.Web.UI.dll but was not handled in user code
 
Additional information: The Document Processing Library fails to convert the RadEditor's content to RadFlowDocument

Here is the aspx:
<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Editor2.aspx.vb" Inherits="Assistente_Legal.Editor2" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <title>Editor de Texto</title>
    <telerik:RadCodeBlock runat="server">
        <script type="text/javascript">
            function saveAsPrompt(arg) {
                //debugger;
                var txt = $get('<%= txtFileName.ClientID%>');
                txt.value = arg;
                var btn = $get('<%= btnSaveAsCallBack.ClientID%>');
                btn.click();
            }
 
            function closeWin() {
                //GetRadWindow().BrowserWindow.location.href = 'Default2.aspx';
                GetRadWindow().close();
            }
            function GetRadWindow() {
                var oWindow = null; if (window.radWindow)
                    oWindow = window.radWindow; else if (window.frameElement.radWindow)
                        oWindow = window.frameElement.radWindow; return oWindow;
            }
        </script>
    </telerik:RadCodeBlock>
</head>
<body>
    <form id="form1" runat="server">
        <telerik:RadScriptManager ID="SM" runat="server">
            <Scripts>
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.Core.js" />
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQuery.js" />
                <asp:ScriptReference Assembly="Telerik.Web.UI" Name="Telerik.Web.UI.Common.jQueryInclude.js" />
            </Scripts>
        </telerik:RadScriptManager>
        <telerik:RadSkinManager ID="SKM" runat="server" ShowChooser="false" Skin="Windows7" />
        <telerik:RadWindowManager ID="WM" runat="server"></telerik:RadWindowManager>
        <telerik:RadFormDecorator ID="FD" runat="server" DecoratedControls="All"></telerik:RadFormDecorator>
        <telerik:RadAjaxLoadingPanel ID="LP" runat="server"></telerik:RadAjaxLoadingPanel>
        <div id="Conteudo" runat="server">
            <telerik:RadAjaxPanel runat="server" LoadingPanelID="LP">
                <telerik:RadToolBar ID="TB" runat="server" EnableRoundedCorners="true" EnableShadows="true">
                    <Items>
                        <telerik:RadToolBarButton ImageUrl="~/Images/save32.png" Value="save"
                            Text="Salvar" ToolTip="Salvar">
                        </telerik:RadToolBarButton>
                        <telerik:RadToolBarButton ImageUrl="~/Images/saveas32.png" Value="saveas"
                            Text="Salvar Como" ToolTip="Salvar Como">
                        </telerik:RadToolBarButton>
                        <telerik:RadToolBarButton ImageUrl="~/Images/pdf32.png" Value="pdf"
                            Text="Exportar para PDF" ToolTip="Exportar para PDF">
                        </telerik:RadToolBarButton>
                        <telerik:RadToolBarButton ImageUrl="~/Images/exit32.png" Value="exit"
                            Text="Sair sem salvar" ToolTip="Sair sem salvar">
                        </telerik:RadToolBarButton>
                    </Items>
                </telerik:RadToolBar>
                <asp:Label runat="server" ID="lblReadOnly" Visible ="false" Text="Visualizando Documento Público, alteração não permitida." ToolTip="Para alterar o conteúdo deste documento, você deve copiá-lo para Meus Documentos primeiro!" />
                <telerik:RadEditor ID="EDT" runat="server" Width="100%" ToolbarMode="RibbonBar" ToolsFile="/Styles/editor_toolbars.xml"
                    Style="min-height: 90%;" EditModes="Design" AutoResizeHeight="true" EnableResize="true">
                    <CssFiles>
                        <telerik:EditorCssFile Value="~/Styles/Editor.css" />
                    </CssFiles>
                    <TrackChangesSettings CanAcceptTrackChanges="False"></TrackChangesSettings>
                </telerik:RadEditor>
            </telerik:RadAjaxPanel>
        </div>
 
        <asp:HiddenField ID="txtFileName" runat="server" />
        <asp:Button ID="btnSaveAsCallBack" runat="server" Text="Button" style="display: none;" />
    </form>
</body>
</html>

Here is the code-behind:
Imports Telerik.Windows.Documents.Flow.Model
Imports Telerik.Windows.Documents.Flow.Model.Styles
Imports Telerik.Windows.Documents.Flow.FormatProviders.Docx
Imports System.IO
Imports Telerik.Web.UI
Imports System.Threading
 
Public Class Editor2
    Inherits System.Web.UI.Page
    Private S As Sessao
 
    Private ReadOnly Property EhNovoDocumento As Boolean
        Get
            Return IsNothing(Request("arq"))
        End Get
    End Property
 
    Private _NomeDoArquivo As String = ""
    Public Property NomeDoArquivo() As String
        Get
            If _NomeDoArquivo.Length = 0 And Not EhNovoDocumento Then _NomeDoArquivo = Request.QueryString("arq")
            Return _NomeDoArquivo
        End Get
        Set(ByVal value As String)
            _NomeDoArquivo = value
        End Set
    End Property
 
    ''' <summary>
    ''' Retorna o diretório indicado pela querystring("dir"), caso não possua, retorna o diretório Meus Documentos do usuário conectado.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private ReadOnly Property Diretorio As String
        Get
            If Not IsNothing(Request("dir")) Then
                Dim dir As String = Request("dir")
                If Mid(dir, 1, dir.Length) <> "/" Then dir &= "/"
                Return dir
            Else
                Return "/Documentos/Usuario/" & S.Usuario.UID & "/Meus Documentos/"
            End If
        End Get
    End Property
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Sessao.IsValid Then S = Sessao.Load Else S = New Sessao() : Sessao.Save(S)
 
        If Not IsPostBack Then
            EDT.DisableFilter(Telerik.Web.UI.EditorFilters.ConvertCharactersToEntities)
            ' EDT.EnableFilter(Telerik.Web.UI.EditorFilters.MakeUrlsAbsolute)
            If Not EhNovoDocumento Then
                Helpers.CarregarDocumento(EDT, Server.MapPath(NomeDoArquivo), S)
                If NomeDoArquivo.Contains("Documentos/Publico") Then desabilitaEdicao()
 
                End If
        End If
        setaDiretoriosEditor()
    End Sub
 
    Private Sub Page_PreRender(sender As Object, e As System.EventArgs) Handles Me.PreRender
        If S.Alert.HaveMessage Then
            If S.Alert.IsPrompt Then
                WM.RadPrompt(Helpers.EncodeJsString(S.Alert.Message), S.Alert.CallBackFn, 300, 100, Nothing, Helpers.EncodeJsString(S.Alert.Title), "")
            Else
                WM.RadAlert(Helpers.EncodeJsString(S.Alert.Message), 250, 150, Helpers.EncodeJsString(S.Alert.Title), "")
            End If
            S.Alert.Dismiss()
        End If
    End Sub
 
    Private Sub desabilitaEdicao()
        For Each B As RadToolBarButton In TB.Items
            If B.Value <> "exit" Then B.Enabled = False
        Next
        lblReadOnly.visible = True
    End Sub
 
    Private Sub setaDiretoriosEditor()
        Dim MeusDocumentosVirtual As String = "~/Documentos/Usuario/" & S.Usuario.UID & "/Meus Documentos/"
        Dim EsteProcessoVirtual As String = ""
 
        If Not IsNothing(Session("Processo")) Then
            Using P As Processo = Session("Processo")
                EsteProcessoVirtual = "~/Documentos/Usuario/" & S.Usuario.UID & "/" & P.ID
            End Using
        End If
        EDT.ImageManager.ViewPaths = {MeusDocumentosVirtual, EsteProcessoVirtual}
        EDT.ImageManager.DeletePaths = {MeusDocumentosVirtual, EsteProcessoVirtual}
        EDT.ImageManager.UploadPaths = {MeusDocumentosVirtual, EsteProcessoVirtual}
        EDT.ImageManager.MaxUploadFileSize = 1048576
        EDT.ImageManager.EnableAsyncUpload = True
        EDT.ImageManager.AllowFileExtensionRename = False
 
    End Sub
    Private Sub TB_ButtonClick(sender As Object, e As RadToolBarEventArgs) Handles TB.ButtonClick
        Select Case e.Item.Value
            Case "save"
                Save()
            Case "saveas"
                SaveAs()
            Case "pdf"
                SaveAsPDF()
            Case "exit"
                ExitWithoutSave()
        End Select
    End Sub
 
    Private Sub Save()
        If Not EhNovoDocumento Then
            DoSave(NomeDoArquivo)
        Else
            S.Alert.Show("Escolha Salvar Como...")
        End If
    End Sub
 
    Private Sub SaveAs()
        S.Alert.CallBackFn = "saveAsPrompt"
        S.Alert.Show("Digite o nome do arquivo.<br>A extensão .docx será adicionada automaticamente.<br>Os seguintes caracteres são permitidos: Letras, Números, Hífen, Espaço e Underline.", "Nome do Arquivo", True)
    End Sub
    Private Sub SaveAsCallBack(ByVal sender As Object, ByVal e As EventArgs) Handles btnSaveAsCallBack.Click
        Dim tempName As String = txtFileName.Value
        If tempName.Length = 0 Or Helpers.RegexMatch(tempName, Helpers.ExpressoesRegulares.LetrasNumerosAcentosEspacoUnderlineHifen) Then
            S.Alert.Show("Nome do Arquivo Inválido!")
        Else
            tempName = Helpers.RemoveExtensao(tempName)
            NomeDoArquivo = Diretorio & tempName & ".docx"
            DoSave(NomeDoArquivo)
        End If
    End Sub
 
    Private Sub SaveAsPDF()
        If NomeDoArquivo.Length = 0 Then
            NomeDoArquivo = Diretorio & "Novo Documento de Texto.PDF"
        Else
            NomeDoArquivo = Helpers.TrocaExtensao(NomeDoArquivo, "PDF")
        End If
        Try
            If File.Exists(NomeDoArquivo) Then File.Delete(NomeDoArquivo)
            Helpers.CriarPDF(EDT.Content, Server.MapPath(NomeDoArquivo), S)
        Catch ex As Exception
            Dim temp As String = LOG.Excecao(ex)
            S.Alert.Show("Falha Ao Tentar exportar para PDF. O Administrador foi notificado sobre este problema.")
            MailUtil.Send("contato@assistentelegal.com.br", "Exceção Detectada", "Falha Ao Tentar Exportar PDF.<br>" & temp)
        Finally
            Dim msg As String
            If EhNovoDocumento Then
                msg = "Documento Salvo em PDF com sucesso em: " & NomeDoArquivo & vbCrLf & "Atenção, o arquivo PDF é somente leitura, se você quiser editar este conteúdo no futuro, escolha 'Salvar Como' e digite o nome do arquivo."
            Else
                msg = "Documento Salvo em PDF com sucesso!"
            End If
            S.Alert.Show(msg)
        End Try
    End Sub
 
    Private Sub ExitWithoutSave()
        Dim script As String = "function f(){closeWin(); Sys.Application.remove_load(f);}Sys.Application.add_load(f);"
        ScriptManager.RegisterStartupScript(Page, Page.GetType(), "key", script, True)
    End Sub
 
    Private Sub DoSave(ByVal ARQ As String)
        'Dim provider As New DocxFormatProvider()
        'Dim document As RadFlowDocument = provider.Import(Input)
 
        If Helpers.EhWord(ARQ) Then EDT.ExportToDocx()
        If Helpers.EhRTF(ARQ) Then EDT.ExportToRtf()
        If Helpers.EhMarkdown(ARQ) Then EDT.ExportToMarkdown()
        If Helpers.EhTexto(ARQ) Then
            Try
                Using externalFile As New StreamWriter(Server.MapPath(ARQ), False)
                    externalFile.Write(EDT.Content)
                End Using
                S.Alert.Show("Documento salvo com sucesso!")
                Response.Redirect("/Editor2.aspx?arq=" & NomeDoArquivo)
            Catch tex As ThreadAbortException
                'ignore this exception
            Catch ex As Exception
                Dim temp As String = LOG.Excecao(ex)
                S.Alert.Show("Falha Ao Tentar Salvar o Arquivo. O Administrador foi notificado sobre este problema.")
                MailUtil.Send("contato@assistentelegal.com.br", "Exceção Detectada", "Falha Ao Tentar Salvar o Arquivo.<br>" & temp)
            End Try
        End If
    End Sub
 
    Private Sub EDT_ExportContent(sender As Object, e As Telerik.Web.UI.EditorExportingArgs) Handles EDT.ExportContent
        'neste momento, a propriedade NomeDoArquivo deverá estar configurada corretamente!!
        Dim ARQ As String = Server.MapPath(NomeDoArquivo)
        Try
            If File.Exists(ARQ) Then File.Delete(ARQ)
            Using externalFile As Stream = File.Create(ARQ)
                Dim b() As Byte = System.Text.Encoding.Default.GetBytes(e.ExportOutput)
                externalFile.Write(b, 0, b.Length)
                e.Cancel = True
            End Using
            S.Alert.Show("Documento salvo com sucesso!")
            Response.Redirect("/Editor2.aspx?arq=" & NomeDoArquivo)
        Catch tex As ThreadAbortException
            'ignore this exception
        Catch ex As Exception
            Dim temp As String = LOG.Excecao(ex)
            S.Alert.Show("Falha Ao Tentar Salvar o Arquivo. O Administrador foi notificado sobre este problema.")
            MailUtil.Send("contato@assistentelegal.com.br", "Exceção Detectada", "Falha Ao Tentar Salvar o Arquivo.<br>" & temp)
        End Try
    End Sub
End Class

The image i'm using is attached.

Thanks for the help.

2 Answers, 1 is accepted

Sort by
0
Luiz
Top achievements
Rank 1
answered on 26 Mar 2015, 03:05 AM
Sorry for the duplicated post.
Its because i got http error 500 posting the first, and didn't noticed it was posted at all..
0
Luiz
Top achievements
Rank 1
answered on 26 Mar 2015, 03:11 PM
Hi, 

i managed to find a solution, not sure if this approach is correct, but here is what i did:

Public Shared Function htmlImgSrcToBase64(ByVal html As String) As String
       Try
           Dim regexStr As String = "<img.+src=[""\'](?<IMGSRC>[^""\']+)[""\']"
           Dim RES As MatchCollection = RegexMatchGroup(html, regexStr)
           For Each R As Match In RES
               Dim tempSrc As String = R.Groups("IMGSRC").Value
               ' Dim tempARQ As String = HttpContext.Current.Server.MapPath(HttpUtility.UrlDecode(tempSrc))
               Dim base64 As String = ""
               If tempSrc.Contains("data:image") Then Continue For
               If tempSrc.Length > 0 Then
                   Dim result As WebResponse = Nothing
                   Dim request As WebRequest = WebRequest.Create(tempSrc)
                   result = request.GetResponse()
                   Dim rStream As Stream = result.GetResponseStream()
                   Dim img As Drawing.Image
                   img = Drawing.Image.FromStream(rStream)
                   base64 = GetStringFromImage(img)
                   html = html.Replace("""" & tempSrc & """", """" & "data:image/" & PegaExtensao(tempSrc) & ";base64," & base64 & """ height=""" & img.Height & """ width=""" & img.Width & """")
               End If
           Next
           Return html
       Catch ex As Exception
           Throw ex
       End Try
   End Function
Public Shared Function GetStringFromImage(ByVal image As Drawing.Image) As String
       If image IsNot Nothing Then
           Dim ic As New Drawing.ImageConverter()
           Dim buffer As Byte() = DirectCast(ic.ConvertTo(image, GetType(Byte())), Byte())
           Return Convert.ToBase64String(buffer, Base64FormattingOptions.InsertLineBreaks)
       Else
           Return Nothing
       End If
   End Function


And before i call the exporttodocx() method, i do this:
EDT.Content = Helpers.htmlImgSrcToBase64(EDT.Content) : EDT.ExportToDocx()

Is this the best approach for this problem?

note that i'm manually setting width and height of the img tag, because if its missing, the image is displayed with widht and height of 1.
one problem with this approach is that when the image is converted, it will reset the width and height of the image to de actual image size, which is bad, in case the user resized the image in the editor.

But after some testing, if the image is already on base64 format, and i export it again, it keeps the correct image size.
Tags
Editor
Asked by
Luiz
Top achievements
Rank 1
Answers by
Luiz
Top achievements
Rank 1
Share this question
or