how to open pdf file from the linkbutton?

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

1jawsAsked:
Who is Participating?
 
demi-osConnect With a Mentor Commented:
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
 
abelCommented:
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
 
1jawsAuthor Commented:
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
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
1jawsAuthor Commented:
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
 
demi-osCommented:
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
 
abelCommented:
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
 
abelCommented:
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
 
1jawsAuthor Commented:
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
 
demi-osCommented:
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
 
demi-osCommented:
edit: please delete the line 8  ->   Response.BinaryWrite(buf);
0
 
abelCommented:
> 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
 
1jawsAuthor Commented:
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
 
abelCommented:
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
 
1jawsAuthor Commented:
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
 
1jawsAuthor Commented:
Thank you. It works.
0
 
abelCommented:
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
 
abelCommented:
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
 
abelCommented:
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
 
1jawsAuthor Commented:
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
 
demi-osCommented:
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
 
1jawsAuthor Commented:
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
 
demi-osCommented:
you need a web application for .NET Framework 3.5 and by default it has required "using System.Linq;"
0
 
1jawsAuthor Commented:
but I have 3.5 installed but I still used asp.net 2.0
0
 
demi-osCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.