• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

skcratch

[Ajuda] - Obter ficheiro pdf em nova janela

20 mensagens neste tópico

Viva!

Na minha aplicação, tenho que implementar uma funcionalidade, na qual o utilizador clica num LinkButton, sendo depois apresentado um ficheiro pdf que se encontra num servidor remoto. Como o referido ficheiro contém informação sensível, estava a pensar implementar a solução por streaming, de modo a ocultar a localização do ficheiro. O código que tenho até ao momento, é o seguinte:

public static void gerarPDF(string nomeFicheiroPDF, string localizacaoFicheirosPDF)
        {
            string ficheiro = localizacaoFicheirosPDF + nomeFicheiroPDF;
            BinaryReader br = null;
            MemoryStream pdfMemoryStream = null;
            
            HttpContext context = HttpContext.Current;
            context.Response.Buffer = true;
            context.Response.Clear();
            context.Response.ClearContent();
            context.Response.ClearHeaders();
            context.Response.ContentType = "application/pdf";
            context.Response.AddHeader("Content-Disposition", nomeFicheiroPDF);

            if (pdfMemoryStream == null)
            {
                WebClient client = new WebClient();

                try
                {
                    pdfMemoryStream = new MemoryStream(client.DownloadData(ficheiro));
                    br = new BinaryReader(pdfMemoryStream);
                    Byte[] dataBytes = br.ReadBytes((int)(pdfMemoryStream.Length - 1));
                    context.Response.BinaryWrite(dataBytes);
                }
                finally
                {
                    client.Dispose();
                    br.Close();
                }
            }
        }

Apenas estou a tentar implementar esta solução porque me foi aconselhada por um colega. Julgo que em termos de segurança, desde que não seja possível obter o path do ficheiro já é suficiente.

Grato desde já pela ajuda,

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Neste momento, já tenho a obtenção do ficheiro pdf implementada. O código é o seguinte:

public static void obterPDF(string nomeFicheiroPDF, string caminhoFicheiroPDF)
        {
            // concatenar o caminho e o nome do ficheiro
            String sFullPath = String.Empty;
            sFullPath = caminhoFicheiroPDF + nomeFicheiroPDF;

            HttpContext context = HttpContext.Current;

            if (sFullPath != null && sFullPath.Length > 4)
            {
                if (sFullPath.Contains(@"\"))
                {
                    try
                    {
                        FileInfo _fileInfo = new FileInfo(sFullPath);
                        if (_fileInfo.Exists)
                        {
                            // Clear the whatever
                            context.Response.Buffer = false;
                            context.Response.Clear();
                            String sContentType = "";
                            // Determine the content type
                            switch (_fileInfo.Extension.ToLower())
                            {
                                case ".dwf":
                                    sContentType = "Application/x-dwf";
                                    break;
                                case ".pdf":
                                    sContentType = "Application/pdf";
                                    break;
                                case ".doc":
                                    sContentType = "Application/vnd.ms-word";
                                    break;
                                case ".ppt":
                                case ".pps":
                                    sContentType = "Application/vnd.ms-powerpoint";
                                    break;
                                case ".xls":
                                    sContentType = "Application/vnd.ms-excel";
                                    break;
                                default:
                                    // Catch-all content type, let the browser figure it out
                                    sContentType = "Application/octet-stream";
                                    break;
                            }
                            
                            context.Response.AddHeader("Content-Disposition", "filename=" + _fileInfo.Name);
                            context.Response.AddHeader("Content-Length", _fileInfo.Length.ToString());
                            context.Response.ContentType = sContentType;
                            context.Response.WriteFile(sFullPath);
                            context.Response.End();
                        }
                    }

                    catch
                    {}
                }
            }
        }

No entanto, tenho um pequeno problema que não sei resolver. Como é ilustrado no código, o ficheiro é apresentado na própria página mas eu gostava que a resposta fosse redireccionada para uma página diferente, de modo a que quando fosse clicado o retroceder no browser, se voltasse para a página original. Alguém sabe como posso fazer isso?

Grato desde já pela ajuda!

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Neste momento, tenho uma GridView onde são apresentados vários registos. Uma das colunas da referida GridView contém um controlo ImageButton, que ao ser clicado invoca o método que foi ilustrado anteriormente. Será que alguém me pode dizer como posso abrir o pdf numa janela?

Grato desde já pela ajuda,

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

podes fazer isso através de javascript, atenção q o browser se tiver bloqueador de popups vai bloquear.

A solução é a seguinte:

metes no linkbutton da grid um onclick com um script em javascript que faz um window.open a outra página.

Nessa outra página, q pode ser um aspx ou um ashx, cm te der jeito, fazes o código para gerar o conteudo do pdf, esse q tens aí em cima (não olhei p ele, mas deve tar certo).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

O método que tenho implementado é apresentado a seguir:

public static void obterPDF(string nomeFicheiroPDF, string caminhoFicheiroPDF)
        {
            // concatenar o caminho e o nome do ficheiro
            String sFullPath = String.Empty;
            sFullPath = caminhoFicheiroPDF + nomeFicheiroPDF;

            HttpContext context = HttpContext.Current;

            if (sFullPath != null && sFullPath.Length > 4)
            {
                if (sFullPath.Contains(@"\"))
                {
                    try
                    {
                        FileInfo _fileInfo = new FileInfo(sFullPath);
                        if (_fileInfo.Exists)
                        {
                            // Clear the whatever
                            context.Response.Buffer = false;
                            context.Response.Clear();
                            String sContentType = "";
                            // Determine the content type
                            switch (_fileInfo.Extension.ToLower())
                            {
                                case ".dwf":
                                    sContentType = "Application/x-dwf";
                                    break;
                                case ".pdf":
                                    sContentType = "Application/pdf";
                                    break;
                                case ".doc":
                                    sContentType = "Application/vnd.ms-word";
                                    break;
                                case ".ppt":
                                case ".pps":
                                    sContentType = "Application/vnd.ms-powerpoint";
                                    break;
                                case ".xls":
                                    sContentType = "Application/vnd.ms-excel";
                                    break;
                                default:
                                    sContentType = "Application/octet-stream";
                                    break;
                            }

                            context.Response.AddHeader("Content-Disposition", "attachment=" + _fileInfo.Name);
                            context.Response.AddHeader("Content-Length", _fileInfo.Length.ToString());
                            // Set the content type
                            context.Response.ContentType = sContentType;
                            // Write the file to the browser sFullPath
                            context.Response.WriteFile(sFullPath);

                            // adicionada posteriormente
                            context.Response.End();
                        }
                    }

                    catch
                    {}
                }
            }
        }

Em relação ao método que tinha apresentado anteriormente apenas alterei a seguinte linha:

context.Reponse.AddHeader("Content-Disposition", "attachment=" + _fileInfo.Name);

Ao colocar o attachment= força o browser a fazer o download, sendo apresentado ao utilizador um popup (se é que se lhe pode chamar assim), no qual escolhe se pretende abrir o ficheiro ou então guardá-lo.

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Em relação à tua proposta de solução, basta adicionar à solução um ficheiro *.ashx com o código do método? Sei que existem algumas diferenças mas nunca implementei nenhuma solução recorrendo a essa aproximação. Uma outra dúvida que tenho é como posso passar o código do ficheiro (equivalente ao nome) para a função onclick como argumento a partir do markup da GridView?

Grato desde já pela ajuda,

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se tiveres a usar markup podes escrever mesmo onclick, apesar d n ser reconhecido pelo intellisense vai funcionar.

tipo: <... onclick="javascript:window.open('~/pagina.ashx')...>

se for por código é à propriedade attributes da gridview q tens q adicionar aquilo.

O q o ashx faz é receber um pedido(Request) e enviar uma resposta(Response), se essa resposta for uma stream com content type pdf... acontece o q queres, pedido p download do pdf.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

E nesse código, como posso enviar o argumento que referi à pouco? Na implementação que tenho, o código (que corresponde ao nome do ficheiro) é enviado como argumento do comando associado ao controlo ImageButton, que por sua vez tem event handler associado para o evento OnCommand. É nesse event handler que concateno o nome do ficheiro ao caminho para a sua localização no servidor e invoco o método anteriormente descrito.

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Pelo que estive a ler, caso utilize a query string referida, essa informação fica visível no url da janela que for aberta com a informação pretendida, não é assim? Acontece algo deste género:

http://dotnetperls.com/?file=logo

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Mas não sei até que ponto não se levantam questões de segurança com este tipo de aproximação...  :down:!

De qualquer forma, vou tentar implementar a solução que propuseste, mais não seja para aprender. Mas pensando bem, não será com o código que é passado na query string que alguém vai conseguir obter alguma informação sensível.

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Questões de segurança só se levantam se passares informação critica pela query string, como passwords.

De resto desde que valides o valor q vem, n há problema.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ok!

Vou então tentar implementar a solução que propuseste. Mais uma vez, obrigado por toda a tua ajuda.

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Pelo que estive a ver, também se podem adicionar alguns parâmetros para pesquisas possam ser realizadas no *.ashx ao webconfig. Qual a vantagem de se fazer isso?

Cumps!

:D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não tou a ver do q tás a falar, podes por um exemplo?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Algo deste género:

<appSettings>
<add key="Pesq_SQLSELECT" value="SELECT NPOL FROM PT10K_NPOLICIA WHERE COD_RUA = @QUERYSTRING ORDER BY 1" />
<add key="Pesq_SQLCHAVE" value="NPOL" />
</appSettings>

Vi este exemplo algures mas não percebo muito bem o seu funcionamento. Uma outra coisa que gostaria de perguntar é como posso executar um script javascript no response do método que mostrei anteriormente. Eu gostaria que fosse executado caso o ficheiro não se encontrasse no directório (apagado acidentalmente, por exemplo). Como o método invocado faz parte de uma Class Library da aplicação, posso invocar scritps que se encontrem registados na página onde se encontra o controlo cujo event handler invocou o método?

Grato desde já pela ajuda,

Cumps!

:confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso não tem nada a ver com os handlers.

Isso são valores q guardas no web.config para usares na tua página.

São guardados aí os valores q variam com facilidade para não estar no código, é sempre mais fácil parametrizar um web.config, do q andar no código á procura desses valores.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Viva!

Obrigado pelos esclarecimentos quanto à questão do web.config. Tens alguma ideia de que forma posso invocar uma função javascript (estou a pensar criar um popup, por exemplo), para alertar o utilizador caso o ficheiro não exista?

Cumps!

:confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Numa página aspx podes adicionar conteudo javascript que será executado no cliente através do RegisterClientScript e/ou RegisterClientScriptBlock.

Não me lembro ao certo da diferença, mas uma leitura sobre isso e já ficas com uma ideia do q precisas.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora