1

my web form creates a file and saves it to a folder in the server that the user can click on and view it in browser:

<asp:Repeater runat="server" ID="rptContent" OnItemCommand="btnGeneratePDF_Click">
            <HeaderTemplate>
                <table id="tblResponse">
                    <tr id="hdrRow">
                        <td style="width: 25%;">Name</td>
                        <td style="width: 25%;">Last Four SSN #</td>
                        <td style="width: 25%;">PDF Generator</td>
                    </tr>
            </HeaderTemplate>
            <ItemTemplate>
                    <tr class="trNormal">
                        <td><%# Eval("name").ToString() %></td>
                        <td><%# Eval("ssn3").ToString() %></td>
                        <td><asp:Button ID="btnGeneratePDF" ClientIDMode="Static" runat="server" Text="Generate PDF" CommandArgument='<%# Eval("name").ToString() + ", " + Eval("ssn3").ToString() %>' /></td>
                    </tr>
            </ItemTemplate>
            <FooterTemplate>
                </table>
            </FooterTemplate>
        </asp:Repeater>

When the user clicks on the Generate PDF button it currently displays a link to the file the user can click on to view the file. The code behind is here:

public void writeData(string k, string c)
    {
        Conn = new SqlConnection(cString);
        Conn.Open();


        string pdfTemplate = Path.Combine(Server.MapPath("~/PDFTemplates/forme.pdf"));
        //MessageBox.Show(pdfTemplate);
        string newFile = strDirectory + "completed_pdf_" + k + ".pdf";
        newFileServer = System.Environment.MachineName + @"/PDFGenerate/completed_pdf_" + k + ".pdf";

        PdfReader pdfReader = new PdfReader(pdfTemplate);
        PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(newFile, FileMode.Create));
        AcroFields pdfFormFields = pdfStamper.AcroFields;

        //if more than multiple entries, verify by name and the last four ssn
        sqlCode = "SELECT * FROM [Db].[dbo].[TablePDF] WHERE [name] = '" + k + "' AND [ssn3] = " + c + "";
        //MessageBox.Show("" + sqlCode.ToString());

        using (SqlCommand command = new SqlCommand(sqlCode, Conn))
        {
            command.CommandType = CommandType.Text;

            using (reader = command.ExecuteReader())
            {
                if (reader.HasRows)
                {
                    if (reader.Read())
                    {
                        pdfFormFields.SetField("lName", reader.GetValue(0).ToString());
                        pdfFormFields.SetField("fName", reader.GetValue(1).ToString());
                        pdfFormFields.SetField("cbMALEpg3", "Yes");
                        tc.Text = "A completed PDF for " + k + " was generated successfully and saved to <a target=_blank href=/PDFGenerate/completed_pdf_" + k + ".pdf>//" + newFileServer + "</a>";
                        strFullPath = Path.GetFullPath("//" + newFileServer);
                        List<System.Web.UI.WebControls.ListItem> files = new List<System.Web.UI.WebControls.ListItem>();
                        files.Add(new System.Web.UI.WebControls.ListItem(strFullPath, strFullPath));
                        GridView1.DataSource = files;
                        GridView1.DataBind();
                    }
                }
            }
        }

        pdfStamper.FormFlattening = false; //allow user to modify the form once it has been saved. Set to TRUE otherwise.

        // close the pdf
        pdfStamper.Close();

        Conn.Close();
    }

The above codes work fine, where the button generates a link in the tc label and I am able to click and view the file in the browser.

The tc label shows this which is a link I can click on and view the pdf file:

A completed PDF for bill was generated successfully and saved to <a href="http://server:85/PDFGenerate/completed_pdf_bill.pdf">//server/PDFGenerate/completed_pdf_bill.pdf</a>

Side note: I created a virtual folder in my site in IIS pointing to the physical folder in the server which stores the files, making the above link work.

The GridView code portion above is to populate a table with the link and a DOWNLOAD and VIEW option that I added on my page here:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" EmptyDataText = "No PDF was generated">
    <Columns>
        <asp:BoundField DataField="Text" HeaderText="File Name" />
        <asp:TemplateField>
            <ItemTemplate>
                <asp:LinkButton ID="lnkDownload" Text = "Download" runat="server" OnClick = "DownloadFile" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:LinkButton ID = "lnkView" Text = "View" runat = "server" OnClick = "ViewFile" />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

I also added the following code to handle the DOWNLOAD command:

protected void DownloadFile(object sender, EventArgs e)
    {
        string strFilePath = Path.GetFullPath("\\\\" + newFileServer);
        MessageBox.Show(strFilePath);
        Response.ContentType = ContentType;
        Response.AppendHeader("Content-Disposition", "attachment; filename=" + strFullPath);
        MessageBox.Show(strFullPath);
        Response.WriteFile(strFilePath);
        Response.End();
    }

I will be accessing that outside of the server that it is on from a local PC which is still in the same network. When I click on the DOWNLOAD link, I get an error: The UNC path should be of the form \\server\share

Right now, the GridView is populating correctly, but the DOWNLOAD link isn't working inside the GridView.

How can I fix the code so the DOWNLOAD link works? Also, what would be the code so make the VIEW link work the way it is currently working in the tc label?

SearchForKnowledge
  • 3,663
  • 9
  • 49
  • 122
  • This is the answer http://stackoverflow.com/questions/10912164/what-is-the-best-way-to-download-file-from-server/10912955#10912955 You make a handler and you send the file using that handler. – Aristos Jun 26 '14 at 15:51

1 Answers1

1

Just stream the bytes back.

 byte[] fileByteArray = File.ReadAllBytes(Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "MyPDF.pdf"));
 Response.AddHeader("Content-disposition", String.Format("attachment; filename={0}.pdf", "MyTestFile"));
 Response.ContentType = "application/octet-stream";
 Response.BinaryWrite(fileByteArray);

UPDATE

Since your files are on the same server hosting your page there is no reason you need to share off the directory if users are only accessing them via your site. Keeping the share either way doesn't matter but there is no need to call a UNC path when the files are local to the page.

I would remove the share and use the following

string myFilename = "report.pdf"
byte[] fileByteArray = File.ReadAllBytes(Path.Combine(@"C:\PDFFolder", myFilename));
Tsukasa
  • 6,342
  • 16
  • 64
  • 96
  • Should the `MyPDF.pdf` should be the filename that I saved as? – SearchForKnowledge Jun 26 '14 at 15:57
  • Yes that's Correct. MyTestFile will be the name it saves to their machine. – Tsukasa Jun 26 '14 at 16:54
  • Thank you. I have a global value that I assign it in my function but when I access it from another function it's empty. – SearchForKnowledge Jun 26 '14 at 17:32
  • Sounds like you should be storing your value in a session variable. Session["MyVarName"] = YourValue. string file = Session["MyVarName"] as string; – Tsukasa Jun 26 '14 at 18:33
  • I think you are right, The page does reload when the button is clicked. – SearchForKnowledge Jun 26 '14 at 18:34
  • Yes you are likely losing your vars so store them in Session – Tsukasa Jun 26 '14 at 19:02
  • I ended up using a `HttpHandler` file to fetch the file but for `File.ReadAllBytes(Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "MyPDF.pdf"));` is failing because the path is like this: `C:\Users\user1\Document\Visual` but the real path is `C:\Users\users\Document\Visual Studio 2012\Project\MyProj\PDFGenerate\filename.pdf`. Is there any way to use the server path instead? Because the website will be accessed from a local PC within the same network. – SearchForKnowledge Jun 26 '14 at 19:37
  • System.Web.Hosting.HostingEnvironment.Applicatio‌​nPhysicalPath Gets the physical path on disk to the application's directory so you would have to adjust to where your generated files are located accordingly – Tsukasa Jun 26 '14 at 19:41
  • The file is actually saved on the server, `C:\PDFFolder\{filename}.pdf` and that is a shared folder. I was giving wrong information myself. Will that be easier now? So from outside of the server the path is `\\myserver\PDFFolder\{filename}.pdf` – SearchForKnowledge Jun 26 '14 at 19:44