Solved

how to open pdf file from the linkbutton?

Posted on 2009-05-12
24
3,130 Views
Last Modified: 2012-05-06
I have a pdf files in folder MY PDF and lets I have two files  
test1.pdf (updated  5/4/09)
test2.pdf (updated  5/5/09)
which means are I need to get the test2.pdf file because that is the latest updated pdf. So, this point how can I generate my code that user will click that Accessing Info link and see that pdf file test2? From the when linkbutton click.. But I get this error messags.

I tested the code , it is giving this problem
'System.Array' does not contain a definition for 'OrderByDescending' and no extension method 'OrderByDescending' accepting a first argument of type 'System.Array' could be found (are you missing a using directive or an assembly reference?)      

'object' does not contain a definition for 'LastWriteTime' and no extension method 'LastWriteTime' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)      

The best overloaded method match for 'System.IO.BinaryReader.Read(byte[], int, int)' has some invalid arguments

complaining about file  filelenght, cannot convert long to int -  do I need to put number that like 386 KB for ex.




protected void LinkButton1_Click(object sender, EventArgs e)

        {

            System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("c:\\myfolder");

            foreach (System.IO.FileInfo file in dir.GetFiles("*.pdf").OrderByDescending((System.Object x) => x.LastWriteTime))

            {

                //Get the first file and exit 

                processFile(file.FullName, file.Length);

                break; // TODO: might not be correct. Was : Exit For 

            } 
 

        }
 

        private void processFile(string fileName, Int64 fileLength)

        {

            System.IO.BinaryReader s = new System.IO.BinaryReader(new System.IO.FileStream(fileName, IO.FileMode.Open));

            byte[] buf = null;

            s.Read(buf, 0, fileLength - 1);

            s.Close();
 

            Response.AddHeader("Content-Type", "application/pdf");

            Response.BinaryWrite(buf);

            //pdf is a byte array 

            Response.Flush();

            Response.Close();

            HttpContext.Current.ApplicationInstance.CompleteRequest();

        }

Open in new window

0
Comment
Question by:1jaws
  • 9
  • 8
  • 7
24 Comments
 
LVL 39

Expert Comment

by:abel
ID: 24368190
There are two things happening here:

1. the errors. They are caused by other parts of your code than you show here. If you receive the error while debugging, the line where the error occurs will light up. Can you show these parts please? The errors are correct, however, in that "object" and "Array" do not have those methods.

2. the actual question: showing PDF to a user. All you need to do is:
  a. put all PDF in a local folder that is accessible from your website (i.e. you can browse to it)
  b. create a link to that website and put that in the <a href="~/linktopdffilehere">link</a>

So, instead of using a linkbutton (which you can do, btw, but it is overhead you don't need) you should create a normal link and set its runat="server" attribute to make it programmable:

<a href="~/pdffile.pdf" id="pdfFileLink" runat="server">open pdf</a>

if you use that, you can access the object pdfFileLink the same way you would access other objects that have an id and you can set its href value (that points to the PDF file) using your code.

NOTE: you do not need to open the PDF, read its contents and send that to the client's browser. That is not possible (not this way, at least) and more importantly, there's no need to do so.

-- Abel --
0
 

Author Comment

by:1jaws
ID: 24368233
Thank you for replying, I have been struggle with this because, what I need to get the latest dated pdf from the location(such as ftp etc). So, while folder keep having updated pdf I wont do anything, it will go find the order by desc  date, that's why code is showing that, but gives error on that part ..
0
 

Author Comment

by:1jaws
ID: 24368286
line 4 it shows error doesnt like the ORderByDescending and the LastWriteTime
line 15 doesnt like the IO in here new System.IO.FileStream(fileName, IO.FileMode.Open));
line 17 doesnt like that whole code in that line (The best overloaded method match for 'System.IO.BinaryReader.Read(byte[], int, int)' has some invalid arguments      ) also says cannot convert long to int.

Those are the errors I got

0
 
LVL 3

Expert Comment

by:demi-os
ID: 24368497
i thinks thats what you need
        protected void button1_Click(object sender, EventArgs e)

        {

            System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("e:\\temp");

            System.IO.FileInfo[] FileInfoArray = dir.GetFiles("*.pdf");
 

            System.IO.FileInfo _last_modified = FileInfoArray[0];
 

            foreach (System.IO.FileInfo _file in FileInfoArray)

            {

                if (_file.LastWriteTime > _last_modified.LastWriteTime) _last_modified = _file;

            }
 

            processFile(_last_modified.FullName, _last_modified.Length);

        }

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24368503
Sorry, you are right, the code with the error is there indeed. Here's how you can remove that error: do not use the object type, in fact, do not use a type at all:

OrderByDescending( x => x.LastWriteTime))
the error you receive about the OrderByDescending might be caused because you are missing an "using System.Linq" on top of your class.

line 15 and 17 are void, because you don't need them anymore. See my earlier post. All you are after is the path info to create your link. You do not want to stream the files, because that is not necessary. If you do need to do this on postback then use a Response.Redirect(yourpdffile).

0
 
LVL 39

Expert Comment

by:abel
ID: 24368564
Btw, in the same way you can add the following on top of your page

using System.IO;
using System.Linq;

You do not need a loop at all. Since you are apparently already using LINQ, you can do the following instead:

// get the file with the highest lastwritetime 

var file = dir.GetFiles("*.*").OrderByDescending(x => x.LastWriteTime).Last();
 

// redirect and show the PDF file to the user

Response.Redirect("~/pdfUploadDir" + file.Name);

Open in new window

0
 

Author Comment

by:1jaws
ID: 24369057
I am confused, demi your code is missing  processFile part? if I use the one I already have it is you know giving me error. on the s.Read(buf, 0, fileLength - 1);  
can I  just the possible working code, if is not too much to ask because I have those codes but not working..
Thanks for helping, I really appreacited..
0
 
LVL 3

Expert Comment

by:demi-os
ID: 24369302
i think i added the needed parts, however cant test the code now, feel free to try it out
        private void processFile(string fileName, long fileLength)

        {

            System.IO.BinaryReader s = new System.IO.BinaryReader(new System.IO.FileStream(fileName, System.IO.FileMode.Open));

            int intBufLen = 1000000;

            byte[] buf = new byte[intBufLen];
 

            Response.AddHeader("Content-Type", "application/pdf");

            Response.BinaryWrite(buf);

            int total_read = 0;

            while (total_read < fileLength)

            {

                int i = s.BaseStream.Read(buf, 0, intBufLen);

                byte[] out_buf = new byte[i];

                Array.Copy(buf, out_buf, i);

                total_read += i;

                Response.BinaryWrite(out_buf);

            }

            s.Close();

            //pdf is a byte array 

            Response.Flush();

            Response.Close();

            HttpContext.Current.ApplicationInstance.CompleteRequest();

        }

Open in new window

0
 
LVL 3

Expert Comment

by:demi-os
ID: 24369310
edit: please delete the line 8  ->   Response.BinaryWrite(buf);
0
 
LVL 3

Accepted Solution

by:
demi-os earned 500 total points
ID: 24369501
tested and working
    protected void button1_Click(object sender, EventArgs e)

    {

        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("e:\\temp");

        System.IO.FileInfo[] FileInfoArray = dir.GetFiles("*.pdf");
 

        System.IO.FileInfo _last_modified = FileInfoArray[0];
 

        foreach (System.IO.FileInfo _file in FileInfoArray)

        {

            if (_file.LastWriteTime > _last_modified.LastWriteTime) _last_modified = _file;

        }
 

        processFile(_last_modified.FullName, _last_modified.Length);

    }

    

    private void processFile(string fileName, long fileLength)

    {

        System.IO.BinaryReader s = new System.IO.BinaryReader(new System.IO.FileStream(fileName, System.IO.FileMode.Open));

        int intBufLen = 1000000;

        byte[] buf = new byte[intBufLen];
 

        Response.AddHeader("Content-Type", "application/pdf");

        //Response.BinaryWrite(buf);

        int total_read = 0;

        while (total_read < fileLength)

        {

            int i = s.BaseStream.Read(buf, 0, intBufLen);

            byte[] out_buf = new byte[i];

            Array.Copy(buf, out_buf, i);

            total_read += i;

            Response.BinaryWrite(out_buf);

        }

        s.Close();

        //pdf is a byte array 

        Response.Flush();

        Response.Close();

        HttpContext.Current.ApplicationInstance.CompleteRequest();

    }

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24369564
> I am confused, demi your code is missing  processFile part?

can you explain to me why you are trying to flush the contents of the pdf file to the client? You are not doing anything with the file, so all you add is more processor consumation. Instead, you should really consider just sending the PDF or the redirect. In addition, that will make it easier for the end-user to create a favorites-link to your PDF.

Of course, if you do have a reason to really write the data to the response stream, you can. But then don't forget to add the following before you start writing something different then a default output stream:

Response.Clear();Response.ClrearHeaders();Response.BufferOUtput = true;
0
 

Author Comment

by:1jaws
ID: 24369582
ok, can you send me to code like demi sent and I can test it and see the difference what you mean..
you saying add those codes to end of the  process file?
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 39

Expert Comment

by:abel
ID: 24369746
Can you please explain in a bit more detail what you are after? I can send you the code, but it is already there (the two lines in my earlier post). It is really that simple if all you need is redirects. But I cannot look into your mind, so I don't know what you requirements are.

From your question I deduct: how to show a pdf, based on pdf on disk.

The answer: the easy way is by using a Response.Redirect or a direct link. Both are explained above and neither need any of the processFile code. Rather the opposite. The two lines that explain the redirect are really the only two lines you need.

Keep one thing in mind though: you use "c:/myfolder", which is probably not the real one. Make sure that the folder of the PDF files is relative to your virtual site directory and you will not get any access denied issues once you publish your website. This rule of thumb accounts for all approaches (also the much more complex one with using the Response streams and reading the contents of the pdf files)
0
 

Author Comment

by:1jaws
ID: 24370000
I put that code and complaining about the using System.Linq;  
The type or namespace name 'Linq' does not exist in the namespace 'System' (are you missing an assembly reference?)      
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("C:\\myfolder");

            // get the file with the highest lastwritetime 

            var file = dir.GetFiles("*.*").OrderByDescending(x => x.LastWriteTime).Last();
 

            // redirect and show the PDF file to the user

            Response.Redirect("C:\\myfolder" + file.Name);

Open in new window

0
 

Author Closing Comment

by:1jaws
ID: 31580677
Thank you. It works.
0
 
LVL 39

Expert Comment

by:abel
ID: 24371810
Ah, very good! Now we're onto something. Either you do not have .NET 3.5, or your references are not in order. Can you add a reference to System.Core? Just right-click on the project, select "Add reference" and under the .NET tab scroll to System.Core. The namespace System.Linq is in there.

If you want to do more with Linq, you may want to add System.Data.Linq as well, but that's not a necessity for this thread.

In your code above you still use System.IO. Now that you have your using-directives set with "using System.IO" you do not need that as prefixes anymore, making your code more readable:

// DON'T FORGET: change this to your real local subdir

System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("C:\\myfolder");
 

// get the file with the highest lastwritetime 

var file = dir.GetFiles("*.pdf").OrderByDescending(x => x.LastWriteTime).Last();

 

// redirect and show the PDF file to the user

Response.Redirect("C:\\myfolder" + file.Name);

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24372193
funny, I missed that the q. was already closed. Well, good that you got it working. Though I gotta say: it is often better to choose the easier path then the harder path (and I apologies about that last code snippet, it does not show what I wanted it to show, so here it is again):

// change this to your real local subdir

DirectoryInfo dir = new DirectoryInfo("C:\\myfolder");

 

// get the file with the highest lastwritetime 

var file = dir.GetFiles("*.pdf").OrderByDescending(x => x.LastWriteTime).Last();

 

// redirect and show the PDF file to the user

Response.Redirect("C:\\myfolder" + file.Name);

Open in new window

0
 
LVL 39

Expert Comment

by:abel
ID: 24373811
Btw, it just occurred to me, but there's a third way of doing this which has the best of both worlds. You do not need to do it all by hand, but you do have the control over the headers that are send to the browser:

Response.WriteFile(yourpdfilehere);
(thought you wanted to know)
0
 

Author Comment

by:1jaws
ID: 24377376
abel,
thank you so much for trying to help all the way even the question was closed, I hated that you missed the points, it is well deserved, but shows clearly that you are not after points rather after helping, that is soo great, I admire people like you!!  I thought you were not going to answer my last question and didnt think that it was fair to demi-os to leave him hanging by not giving to points to him since his code  was completely working. So, I am going to open up the second part of the this question and ask that I need to have easy way to do that which I need,( like you said easy it better) so will try your code , please be specific like demi-os to show to code snippet what exactly i need to put to my page..Yes, I am using 2.0 still with  2008...
Thanks again!
0
 
LVL 3

Expert Comment

by:demi-os
ID: 24377512
abel's version is better and it will be something like this:

    protected void button1_Click(object sender, EventArgs e)

    {

        System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo("E:\\temp");
 

        var file = dir.GetFiles("*.pdf").OrderByDescending(x => x.LastWriteTime).First();
 

        Response.AddHeader("Content-Type", "application/pdf");

        Response.WriteFile(file.FullName);

    }

Open in new window

0
 

Author Comment

by:1jaws
ID: 24377559
I have added this question for this http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_24405709.html

demi-os, do I need to add the anything to top of the page using ... part ? I get in trouble with namespacings etc.. :)
0
 
LVL 3

Expert Comment

by:demi-os
ID: 24377626
you need a web application for .NET Framework 3.5 and by default it has required "using System.Linq;"
0
 

Author Comment

by:1jaws
ID: 24377646
but I have 3.5 installed but I still used asp.net 2.0
0
 
LVL 3

Expert Comment

by:demi-os
ID: 24377759
at the solution explorer right click at your project -> property pages
check Build -> Target Framework and References

or try to make new project and use "ASP.NET web application" template with Framework 3.5 selected
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
A quick way to get a menu to work on our website, is using the Menu control and assign it to a web.sitemap using SiteMapDataSource. Example of web.sitemap file: (CODE) Sample code to add to the page menu: (CODE) Running the application, we wi…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now