0

I'm using this tutorial https://web.archive.org/web/20211020001747/https://www.4guysfromrolla.com/articles/030211-1.aspx that’s uses a PDF template, lets the user input fields using textbox's. The file downloads onto the client’s pc but I would like to save a copy of the file into a sql database also or just save the file in the database instead of both.

protected void btnGeneratePDF_Click(object sender, EventArgs e)
{
    var pdfPath = Path.Combine(Server.MapPath("~/PDFTemplates/fw9.pdf"));

    // Get the form fields for this PDF and fill them in!
    var formFieldMap = PDFHelper.GetFormFieldNames(pdfPath);
    formFieldMap["topmostSubform[0].Page1[0].f1_01_0_[0]"] = txtName.Text;
    formFieldMap["topmostSubform[0].Page1[0].f1_02_0_[0]"] = txtBusinessName.Text;

    if (rblTaxClassification.SelectedValue != null)
    {
        var formFieldName = string.Format("topmostSubform[0].Page1[0].c1_01[{0}]", rblTaxClassification.SelectedIndex);
        formFieldMap[formFieldName] = (rblTaxClassification.SelectedIndex + 1).ToString();
    }

    if (chkExemptPayee.Checked)
        formFieldMap["topmostSubform[0].Page1[0].c1_01[7]"] = "8";
        

    formFieldMap["topmostSubform[0].Page1[0].f1_04_0_[0]"] = txtAddress.Text;
    formFieldMap["topmostSubform[0].Page1[0].f1_05_0_[0]"] = txtCityStateZIP.Text;
    formFieldMap["topmostSubform[0].Page1[0].f1_07_0_[0]"] = txtAccountNumbers.Text;

    // Requester's name and address (hard-coded)
    formFieldMap["topmostSubform[0].Page1[0].f1_06_0_[0]"] = "Acme Website\n123 Anywhere Lane\nSpringfield, USA";

    // SSN
    if (!string.IsNullOrEmpty(txtSSN1.Text))
    {
        formFieldMap["topmostSubform[0].Page1[0].social[0].TextField1[0]"] = txtSSN1.Text;
        formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[0]"] = txtSSN2.Text;
        formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[1]"] = txtSSN3.Text;
    }
    else if (!string.IsNullOrEmpty(txtEIN1.Text))
    {
        formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[2]"] = txtEIN1.Text;
        formFieldMap["topmostSubform[0].Page1[0].social[0].TextField2[3]"] = txtEIN2.Text;
    }

    var pdfContents = PDFHelper.GeneratePDF(pdfPath, formFieldMap);

    PDFHelper.ReturnPDF(pdfContents, "Completed-W9.pdf");

    FileStream fs = new FileStream(pdfPath, FileMode.Open, FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);
    Byte[] bytes = br.ReadBytes((Int32)fs.Length);
    br.Close();
    fs.Close();

    //insert the file into database
    string strQuery = "insert into tblFiles(Name, ContentType, Data) values (@Name, @ContentType, @Data)";
    SqlCommand cmd = new SqlCommand(strQuery);
    cmd.Parameters.Add("@Name", SqlDbType.VarChar).Value = "Completed-W9132.pdf";
    cmd.Parameters.Add("@ContentType", SqlDbType.VarChar).Value = "application/pdf";
    cmd.Parameters.Add("@Data", SqlDbType.Binary).Value = bytes;
    InsertUpdateData(cmd);

App_code/pdfHelper.cs

using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Web;
using System.IO;
using iTextSharp.text.pdf;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;  

public class PDFHelper
{
    public static Dictionary<string, string> GetFormFieldNames(string pdfPath)
    {
        var fields = new Dictionary<string, string>();

        var reader = new PdfReader(pdfPath);
        foreach (DictionaryEntry entry in reader.AcroFields.Fields)
            fields.Add(entry.Key.ToString(), string.Empty);
        reader.Close();

        return fields;
    }

    public static byte[] GeneratePDF(string pdfPath, Dictionary<string, string> formFieldMap)
    {
        var output = new MemoryStream();
        var reader = new PdfReader(pdfPath);
        var stamper = new PdfStamper(reader, output);
        var formFields = stamper.AcroFields;

        foreach (var fieldName in formFieldMap.Keys)
            formFields.SetField(fieldName, formFieldMap[fieldName]);

        stamper.FormFlattening = true;
        stamper.Close();
        reader.Close();

        return output.ToArray();
    }

    // See http://stackoverflow.com/questions/4491156/get-the-export-value-of-a-checkbox-using-itextsharp/
    public static string GetExportValue(AcroFields.Item item)
    {
        var valueDict = item.GetValue(0);
        var appearanceDict = valueDict.GetAsDict(PdfName.AP);

        if (appearanceDict != null)
        {
            var normalAppearances = appearanceDict.GetAsDict(PdfName.N);
            // /D is for the "down" appearances.

            // if there are normal appearances, one key will be "Off", and the other
            // will be the export value... there should only be two.
            if (normalAppearances != null)
            {
                foreach (var curKey in normalAppearances.Keys)
                    if (!PdfName.OFF.Equals(curKey))
                        return curKey.ToString().Substring(1); // string will have a leading '/' character, so remove it!
            }
        }

        // if that doesn't work, there might be an /AS key, whose value is a name with 
        // the export value, again with a leading '/', so remove it!
        var curVal = valueDict.GetAsName(PdfName.AS);
        if (curVal != null)
            return curVal.ToString().Substring(1);
        else
            return string.Empty;
    }

    public static void ReturnPDF(byte[] contents)
    {
        ReturnPDF(contents, null);
    }

    public static void ReturnPDF(byte[] contents, string attachmentFilename)
    {
        var response = HttpContext.Current.Response;

        if (!string.IsNullOrEmpty(attachmentFilename))
            response.AddHeader("Content-Disposition", "attachment; filename=" + attachmentFilename);

        response.ContentType = "application/pdf";
        response.BinaryWrite(contents);
          response.End();
    }
}
Kᴀτᴢ
  • 2,146
  • 6
  • 29
  • 57
  • It all depends on what DB you're using, but the general approach would be to store it in a "raw data" field, e.g. `varbinary` on SQL Server. Your question is far too broad to answer (in fact, you didn't even ask a question). – Magnus Grindal Bakken Sep 16 '13 at 13:15
  • I'm sorry how would you save the file to a sql database from itextsharp? I can save a pdf to sql just can't connect the too together. – user2784069 Sep 16 '13 at 13:53

1 Answers1

1

The parts of the tutorial you're looking for in that case are right here:

Response.ContentType = "application/pdf";
Response.BinaryWrite(output.ToArray());

When saving a "file" to a database you essentially care about two (maybe three) things:

  • The byte array of the file contents
  • The type of the file
  • (Maybe a name for the file)

Since the tutorial concludes with two of these things (above), the type and the data, you can store these two things into your database however you need to store them. This depends on the database you're using, how you access that database, etc. Essentially to store these two things you just need a text column (varchar?) and a binary (or "blob") column (varbinary?).

The only difference is that instead of setting the type as a header in an HTTP response and writing the bytes to that HTTP response, you're using both of them as values in your database. Everything else is the same.

David
  • 208,112
  • 36
  • 198
  • 279
  • Thanks for your help, I have got the file saving to the database now but its not recording the users input. – user2784069 Sep 16 '13 at 15:25
  • @user2784069: At what point does it fail? It's best to update the question with the new information, including code used and indications of how that code isn't working as expected. Are you sure you're outputting the same byte array to the database which you are outputting to the user? – David Sep 16 '13 at 15:29
  • Hi sorry new to forums. I have edited my previous question with the code. But I think it’s this section is the problem FileStream fs = new FileStream(pdfPath, FileMode.Open, FileAccess.Read); – user2784069 Sep 16 '13 at 15:39
  • @user2784069: It looks like you're opening the local PDF file, populating it with data, returning the populated version to the user... then re-opening the local PDF file and saving it to the database. You need to save the version that you're returning to the user (which has the data in it) to the database, not just the local file. `pdfContents` should have what you want to save. – David Sep 16 '13 at 15:42
  • Thanks when i change pdfpath to pdf content i get the following error Compiler Error Message: CS1502: The best overloaded method match for 'System.IO.FileStream.FileStream(string, System.IO.FileMode, System.IO.FileAccess)' has some invalid arguments. – user2784069 Sep 16 '13 at 16:13
  • @user2784069: You're misunderstanding some fundamental concepts here. The `pdfContent` variable isn't a file that's on your server. You can't open it with a `FileStream`. It's entirely in-memory in your code. I can't tell what type it is from the code, but it either is or contains a byte array of data. That's the data you want to save to your database. – David Sep 16 '13 at 16:17
  • Thanks for help. I think I don’t have the knowledge to complete the task. Just can’t make the output write in the PDFHelper.cs – user2784069 Sep 16 '13 at 16:40
  • Hi David, Thanks again for your time & guidance yesterday. I finally got it work with one line of code. Feel so studied. byte[] content = output.ToArray(); in PDF helper.cs (GeneratePDF) – user2784069 Sep 17 '13 at 10:19