+6 votos
137 visitas
Fiz uma rotina utilizando BEF, que consiste em gerar alguns registros e armazenar um relatório no formato PDF. Nesse registro também é armazenado um caminho da web juntamente com o handle do registro criptografado. Cada registro contém um e-mail de cliente. Através do e-mail mando esse link para os clientes.

Pois bem, o que eu preciso é que ao clicar nesse link o cliente baixe esse relatório sem que haja uma identificação/autenticação, ele apenas deve ter acesso ao registro e ao relatório armazenado. A dificuldade é como criar essa pagina que tenha acesso aos dados do sistema e ao mesmo tempo possa ser acessada por esse link.

Existe alguma forma de fazer isso?
por (155 pontos)
editado por | 137 visitas

2 Respostas

+3 votos
Melhor resposta

Esta seria uma proposta de solução, vou detalhar como seria desde o envio do e-mail até a página especializada para fazer o download do relatório.

Regra de negócio (BEF)

Responsável por enviar o link para o usuário, no link é adicionado dois parâmetros o nome do usuário e o handle critografado do relatório, que serão utilizados na página especializada.

 

var mailMessage = new MailMessage();
mailMessage.SendTo = email;

//Gerar um link com dois parâmetros
var urlLinkDefinition = new UrlLinkDefinition(url);
//Nome do usuário
urlLinkDefinition.Parameters.Add("UserName", userName);
//Handle criptografado
urlLinkDefinition.Parameters.Add("EncryptedHandle", encryptedHandle);

mailMessage.Subject = "Relatório";
mailMessage.Body = string.Format(@"Olá {0},

Abaixo o link para download do relatório:

{1}

", userName, urlLinkDefinition.GetEncodedUrl());

mailMessage.Send();

 

Página especializada (WES)

Criar uma pagina ashx no WES, que esteja configurada como uma página publica no web.config:

  <!-- Permitir acesso a usuários não autenticados na página de baixar relatório-->
  <location path="BaixarRelatorio.ashx">
    <system.web>
      <authorization>
        <allow users="?" />
      </authorization>
    </system.web>
  </location>

Na pagina especializada, você deve verificar se os parâmetros são coerentes com a requisição para que seja garantido a segurança:

public class BaixarRelatorio : IHttpHandler, IReadOnlySessionState
    {

        public void ProcessRequest(HttpContext context)
        {
            //prms é o nome do parâtro criado pela classe UrlLinkDefinition
            if (context.Request["prms"] != null)
            {
                var urlLinkDefinition = new UrlLinkDefinition(context.Request.Url.AbsoluteUri);
                urlLinkDefinition.DeserializeParameters(context.Request["prms"].ToString());

                var userName = urlLinkDefinition.Parameters["UserName"].ToString();
                var encryptedHandle = urlLinkDefinition.Parameters["EncryptedHandle"].ToString();

                var entidadeDoRelatorio = null;
                try
                {
                    entidadeDoRelatorio = EntidadeDoRelatorio.Get(userName, encryptedHandle);
                }
                catch (EntityNotFoundException err)
                {
                    throw err;
                }
                
                //Campo do relatório
                FileField campoRelatorio = entidadeDoRelatorio.Fields["CAMPO_DO_RELATORIO"] as FileField;

                MemoryStream stream = new MemoryStream();
                //Carregando o relatório do bdoc
                FileField.RetrieveContents(entidadeDoRelatorio, "CAMPO_DO_RELATORIO", stream);

                System.Net.Mime.ContentDisposition disposition = new System.Net.Mime.ContentDisposition();
                disposition.DispositionType = System.Net.Mime.DispositionTypeNames.Attachment;

                context.Response.ContentType = "application/pdf";
                
                //Adiciona nome do relatório no cabeçalho
                disposition.FileName = HttpUtility.UrlEncode(fileField.Name);
                context.Response.AddHeader("Content-Disposition", disposition.ToString());

                BinaryReader sr = new BinaryReader(stream);
                context.Response.AddHeader("Content-Length", stream.Length.ToString());
                if (stream.Length > 0)
                {
                    sr.BaseStream.Position = 0;
                    context.Response.BinaryWrite(sr.ReadBytes(Convert.ToInt32(stream.Length)));
                }
                context.Response.Flush();

                context.Response.End();

            }
        }

    }

 

por (470 pontos)
selecionada por
+2 votos

Utilizando o WES, basta criar um novo arquivo Generic Handler (pelo Visual Studio): Relatorio.ashx.

Configure o arquivo web.config para permitir o acesso anônimo a esse Handler:

<location path="Relatorio.ashx">
    <system.web>
        <authorization>
            <allow users="?"/>
        </authorization>
    </system.web>
</location>

Implemente o Handler para obter o arquivo de acordo com os parâmetros da URL e retorná-lo ao navegador.

<%@ WebHandler Language="C#" Class="Relatorio" %>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Benner.Tecnologia.Common;
using Benner.Tecnologia.Common.Instrumentation;
using Benner.Tecnologia.Business;

using Microsoft.Win32;

public class Relatorio : IHttpHandler {

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    public void ProcessRequest(HttpContext context)
    {
        // Obtenção dos parâmetros
        context.Request.Params.Get("CHAVE");

        // Obtém a entidade (utilizando as informações dos parâmetros)
        EntityBase entity = Entity.Get(EntityDefinition.GetByName("TABELA"), new Criteria());

        FileField fileField = entity.Fields["CAMPO"] as FileField;

        // Obtem os dados do campo e retorna  para o navegador
        MemoryStream memoryStream = new MemoryStream();
        FileField.RetrieveContents(entity, "CAMPO", memoryStream);

        string contentType = "application/octet-stream";
        string contentDisposition = "attachment";

        string fileName = Path.GetFileNameWithoutExtension(fileField.Name).Replace('"', '_');
        string fileExtension = Path.GetExtension(fileField.Name).ToLower();
        switch (fileExtension)
        {
            case ".pdf":
                contentType = "application/pdf";
                contentDisposition = "inline";
                break;
            case ".rtf":
                contentType = "text/rtf";
                contentDisposition = "inline";
                break;
            case ".doc":
                contentType = "application/msword";
                contentDisposition = "inline";
                break;
            case ".xls":
                contentType = "application/vnd.ms-excel";
                contentDisposition = "inline";
                break;
            case ".dat":
                contentType = "application/octet-stream";
                contentDisposition = "attachment";
                break;
            case ".csv":
                contentType = "text/csv";
                contentDisposition = "attachment";
                break;
            default:
                RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(fileExtension);
                contentType = registryKey != null ? (string)registryKey.GetValue("Content Type", "application/octet-stream") : "application/octet-stream";
                contentDisposition = "attachment";
                break;
        }

        context.Response.ClearHeaders();
        context.Response.ClearContent();
        context.Response.Clear();
        context.Response.ContentType = contentType;
        context.Response.AddHeader("Content-Disposition", String.Format("{0}; filename=\"{1}{2}\"", contentDisposition, fileName, fileExtension));
        context.Response.AddHeader("Content-Length", memoryStream.Length.ToString());

        BinaryReader binaryReader = new BinaryReader(memoryStream);
        if (memoryStream.Length > 0)
        {
            binaryReader.BaseStream.Position = 0;
            context.Response.BinaryWrite(binaryReader.ReadBytes(Convert.ToInt32(memoryStream.Length)));
        }

        context.Response.Flush();
        context.Response.End();
    }
}

 

por (224 pontos)
Melhores Nov 2020
  1. kevin.katzer

    13 Pontos

  2. Cesar.Albuquerque

    11 Pontos

  3. diuari.molinari

    1 Pontos

200 pontos
Melhores 2020 Nov 23 - 29
    445 perguntas
    492 respostas
    351 comentários
    497 usuários