Problem Exporting Content with Image to DOCX

3 posts, 0 answers
  1. Luiz
    Luiz avatar
    3 posts
    Member since:
    Mar 2015

    Posted 25 Mar 2015 Link to this post

    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) {
                    var txt = $get('<%= txtFileName.ClientID%>');
                    txt.value = arg;
                    var btn = $get('<%= btnSaveAsCallBack.ClientID%>');
                function closeWin() {
                    //GetRadWindow().BrowserWindow.location.href = 'Default2.aspx';
                function GetRadWindow() {
                    var oWindow = null; if (window.radWindow)
                        oWindow = window.radWindow; else if (window.frameElement.radWindow)
                            oWindow = window.frameElement.radWindow; return oWindow;
        <form id="form1" runat="server">
            <telerik:RadScriptManager ID="SM" runat="server">
                    <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" />
            <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">
                            <telerik:RadToolBarButton ImageUrl="~/Images/save32.png" Value="save"
                                Text="Salvar" ToolTip="Salvar">
                            <telerik:RadToolBarButton ImageUrl="~/Images/saveas32.png" Value="saveas"
                                Text="Salvar Como" ToolTip="Salvar Como">
                            <telerik:RadToolBarButton ImageUrl="~/Images/pdf32.png" Value="pdf"
                                Text="Exportar para PDF" ToolTip="Exportar para PDF">
                            <telerik:RadToolBarButton ImageUrl="~/Images/exit32.png" Value="exit"
                                Text="Sair sem salvar" ToolTip="Sair sem salvar">
                    <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">
                            <telerik:EditorCssFile Value="~/Styles/Editor.css" />
                        <TrackChangesSettings CanAcceptTrackChanges="False"></TrackChangesSettings>
            <asp:HiddenField ID="txtFileName" runat="server" />
            <asp:Button ID="btnSaveAsCallBack" runat="server" Text="Button" style="display: none;" />

    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
                Return IsNothing(Request("arq"))
            End Get
        End Property
        Private _NomeDoArquivo As String = ""
        Public Property NomeDoArquivo() As String
                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
                If Not IsNothing(Request("dir")) Then
                    Dim dir As String = Request("dir")
                    If Mid(dir, 1, dir.Length) <> "/" Then dir &= "/"
                    Return dir
                    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.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
        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), "")
                    WM.RadAlert(Helpers.EncodeJsString(S.Alert.Message), 250, 150, Helpers.EncodeJsString(S.Alert.Title), "")
                End If
            End If
        End Sub
        Private Sub desabilitaEdicao()
            For Each B As RadToolBarButton In TB.Items
                If B.Value <> "exit" Then B.Enabled = False
            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"
                Case "saveas"
                Case "pdf"
                Case "exit"
            End Select
        End Sub
        Private Sub Save()
            If Not EhNovoDocumento Then
                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!")
                tempName = Helpers.RemoveExtensao(tempName)
                NomeDoArquivo = Diretorio & tempName & ".docx"
            End If
        End Sub
        Private Sub SaveAsPDF()
            If NomeDoArquivo.Length = 0 Then
                NomeDoArquivo = Diretorio & "Novo Documento de Texto.PDF"
                NomeDoArquivo = Helpers.TrocaExtensao(NomeDoArquivo, "PDF")
            End If
                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("", "Exceção Detectada", "Falha Ao Tentar Exportar PDF.<br>" & temp)
                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."
                    msg = "Documento Salvo em PDF com sucesso!"
                End If
            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
                    Using externalFile As New StreamWriter(Server.MapPath(ARQ), False)
                    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("", "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)
                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("", "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. Luiz
    Luiz avatar
    3 posts
    Member since:
    Mar 2015

    Posted 25 Mar 2015 in reply to Luiz Link to this post

    Sorry for the duplicated post.
    Its because i got http error 500 posting the first, and didn't noticed it was posted at all..
  3. DevCraft R3 2016 release webinar banner
  4. Luiz
    Luiz avatar
    3 posts
    Member since:
    Mar 2015

    Posted 26 Mar 2015 Link to this post


    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
               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
               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)
               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.
Back to Top