0

currently i finished developing my PDF webapp where i can generate various PDF. However, i need to have a common download PDF directory for both my mobile phone and computer when accessed by the users.

As for now, when i try to run my webapp on the localhost, this is how i save my PDF file. However, not all computer have the similiar file directory when i published my webapp online/

var output = new FileStream(Path.Combine("C:\\Users\\apr13mpsip\\Downloads", filename), FileMode.Create);

Therefore, i would like to ask if any one has any idea on a common file directory for both mobile phone and computer.

PDFbutton

protected void btnPDF_Click(object sender, EventArgs e)
    {

        var doc1 = new Document();
        var filename = "MyTestPDF" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf";
        var output = new FileStream(Path.Combine("C:\\Users\\apr13mpsip\\Downloads", filename), FileMode.Create);
        iTextSharp.text.pdf.PdfWriter.GetInstance(doc1, output);
        doc1.Open();

        PdfPTable table = new PdfPTable(1);
        table.TotalWidth = 585f;
        table.LockedWidth = true;

        var logo = iTextSharp.text.Image.GetInstance(Server.MapPath("~/image/logo.jpg"));
        doc1.Add(logo);

        var titleFont = FontFactory.GetFont("Arial", 18, Font.BOLD);
        doc1.Add(new Paragraph("Officer's Profile. Officer's Police ID: " + DDLCase.SelectedValue, titleFont));

        var normalFont = FontFactory.GetFont(FontFactory.HELVETICA, 14, Font.BOLD);
        var phrase = new Phrase();

        SqlConnection con = new SqlConnection("Data Source = localhost; Initial Catalog = project; Integrated Security = SSPI");

        SqlCommand cm = new SqlCommand("Select lrp.fullname,  pp.profilepic, pp.rank, lrp.policeid, lrp.nric, lrp.email, lrp.contact, lrp.address,lrp.location, pp.achievement, pp.medal1, pp.medal2, pp.medal3, pp.medal4, pp.medal5 from LoginRegisterPolice lrp, PoliceProfile pp where lrp.policeid = '" + DDLCase.SelectedValue + "' and pp.policeid = lrp.policeid", con);
        con.Open();
        SqlDataReader dr;

        dr = cm.ExecuteReader();

        if (dr.Read())
        {
            phrase.Add(new Chunk("Full Name :", normalFont));
            phrase.Add(dr[0].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);


            phrase.Add(new Chunk("Profile Picture :\u00a0", normalFont));
            Byte[] bytes1 = (Byte[])dr[1];
            iTextSharp.text.Image image1 = iTextSharp.text.Image.GetInstance(bytes1);
            image1.ScaleToFit(100f, 250f);
            Chunk imageChunk1 = new Chunk(image1, 0, 0);
            phrase.Add(imageChunk1);

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Rank : ", normalFont));
            Byte[] bytes2 = (Byte[])dr[2];
            iTextSharp.text.Image image2 = iTextSharp.text.Image.GetInstance(bytes2);
            image2.ScaleToFit(40f, 300f);
            Chunk imageChunk2 = new Chunk(image2, 0, 0);
            phrase.Add(imageChunk2);

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Police ID :", normalFont));
            phrase.Add(dr[3].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("NRIC :", normalFont));
            phrase.Add(dr[4].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Email :", normalFont));
            phrase.Add(dr[5].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Contact :", normalFont));
            phrase.Add(dr[6].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Address :", normalFont));
            phrase.Add(dr[7].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Location :", normalFont));
            phrase.Add(dr[8].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);

            phrase.Add(new Chunk("Achievement :", normalFont));
            phrase.Add(dr[9].ToString());

            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);
            phrase.Add(Chunk.NEWLINE);



            phrase.Add(new Chunk("Medal1", normalFont));
            Byte[] bytes3 = (Byte[])dr[10];
            iTextSharp.text.Image image3 = iTextSharp.text.Image.GetInstance(bytes3);
            image3.ScaleToFit(800f, 800f);
            Chunk imageChunk3 = new Chunk(image3, 0, 0);
            phrase.Add(imageChunk3);


            phrase.Add(new Chunk("Medal2", normalFont));
            Byte[] bytes5 = (Byte[])dr[11];
            iTextSharp.text.Image image5 = iTextSharp.text.Image.GetInstance(bytes5);
            image5.ScaleToFit(800f, 800f);
            Chunk imageChunk5 = new Chunk(image5, 0, 0);
            phrase.Add(imageChunk5);



            phrase.Add(new Chunk("Medal3", normalFont));
            Byte[] bytes6 = (Byte[])dr[12];
            iTextSharp.text.Image image6 = iTextSharp.text.Image.GetInstance(bytes6);
            image6.ScaleToFit(800f, 800f);
            Chunk imageChunk6 = new Chunk(image6, 0, 0);
            phrase.Add(imageChunk6);          

            phrase.Add(new Chunk("Medal4", normalFont));
            Byte[] bytes7 = (Byte[])dr[13];
            iTextSharp.text.Image image7 = iTextSharp.text.Image.GetInstance(bytes7);
            image7.ScaleToFit(800f, 800f);
            Chunk imageChunk7 = new Chunk(image7, 0, 0);
            phrase.Add(imageChunk7);

            phrase.Add(new Chunk("Medal5", normalFont));
            Byte[] bytes8 = (Byte[])dr[14];
            iTextSharp.text.Image image8 = iTextSharp.text.Image.GetInstance(bytes8);
            image8.ScaleToFit(800f, 800f);
            Chunk imageChunk8 = new Chunk(image8, 0, 0);
            phrase.Add(imageChunk8);

            table.AddCell(phrase);


        }

        dr.Close();
        doc1.Add(table);
        doc1.Close();
        btnPDF.Enabled = false;
    }
}
Bryan
  • 8,488
  • 14
  • 52
  • 78
  • I don't get why/how your web app is saving files for users. When I visit a web site **I** request files and **I** choose where they are saved to. For the server to put something on **my** machine without my permission would be a security breach. Am I misunderstanding something? – Chris Haas Jul 09 '13 at 19:59
  • It's my first time trying to use iTextSharp in my webapp though. Therefore i'm actually not very sure on how to choose where would the user like to save his file :/ – Bryan Jul 10 '13 at 01:07
  • Once you have your PDF created you just need to push those bytes to the client with some headers that give the client an idea what to do with them. If you're creating a file on the server you can then just do `Response.WriteFile()` and add a PDF header. If you've got a raw byte array you can do the same but use `Response.BinaryWrite()`. Searching on those will give you some better examples. Is that what you're talking about? – Chris Haas Jul 10 '13 at 01:12
  • I have editted my question on how my PDF works. Honestly, initially i didnt know if response.writefile() works while generating PDF. As what i have researched, filestream actually saves the file into the server. And i do not have any raw bytearray for response.binarywrite(). Whenever the client click the button, it just directly saves into the hard-coded directory which is a security breach. Hence, i'm wondering how to do a "save as" function along with a common file directory on the computer and phone. I have you bear with me as it's my first time using iTextSharp with c# – Bryan Jul 10 '13 at 01:43

4 Answers4

1

Okay, based on your comments I hope this helps you out.

The second parameter of iTextSharp.text.pdf.PdfWriter.GetInstance() is actually a generic System.IO.Stream object. This means that you can pass any object that inherits from that object. There are several types that do but the two most helpful in this case are System.IO.FileStream that you usually use and System.IO.MemoryStream. The MemoryStream class is like an "in-memory file" basically but luckily you don't have to even think about that. The only difference from your standpoint when using a MemoryStream is that when you've closed your Document you need extract the bytes and that can be done with one simple line.

Below is sample code that shows this off. First it creates an empty array of bytes that we'll later store our PDF in. Then in creates a MemoryStream instead of a FileStream. Then it creates a very simple PDF. Once that's done it dumps the bytes from the MemoryStream into the byte array that we created above. After that iTextSharp is no longer involved and we're only dealing with ASP.Net.

(Side note: Instead of writing to a MemoryStream, extracting the bytes and pumping those to the browser you will often see people writing directly to Response.OutputStream. This is 100% valid but I recommend against do it because it can be harder to debug. I prefer to do my iTextSharp work first and debug any errors, then deal with ASP.Net and browser issues.)

protected void btnPDF_Click(object sender, EventArgs e) {
    //Byte array that will eventually hold our PDF, currently empty
    Byte[] bytes;

    //Instead of a FileStream we'll use a MemoryStream
    using (var MS = new System.IO.MemoryStream()) {

        //Standard PDF setup, iText doesn't care what type of stream we're using
        var doc = new iTextSharp.text.Document();
        var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, MS);
        doc.Open();
        doc.Add(new iTextSharp.text.Paragraph("Hello world"));
        doc.Close();

        //Grab the raw bytes from the MemoryStream
        bytes = MS.ToArray();
    }



    //At this point all iText work is done and we're only dealing with raw ASP.Net parts

    //Clear the current response buffer
    Response.Clear();
    //Instead of a normal text/html header tell the browser that we've got a PDF
    Response.ContentType = "application/pdf";
    //Tell the browser that you want the file downloaded (ideally) and give it a pretty filename
    Response.AddHeader("content-disposition", "attachment;filename=MySampleFile.pdf");
    //Write our bytes to the stream
    Response.BinaryWrite(bytes);
    //Close the stream (otherwise ASP.Net might continue to write stuff on our behalf)
    Response.End();
}

Also, this creates a file that a user's browser should download. However, depending on the browser and how the user has configured their browser you might get different results. For instance, Google Chrome on my machine downloads the file immediately to my current download folder which I previously set. Mozilla Firefox, on the other hand, prompts me pick where I want to save the file. (My Internet Explorer for some reason doesn't want to talk to localhost today so I'm not sure what it would do.)

Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • I tried it on my localhost but there isn't any response from the browser. When i used chrome and firefox nothing happened when i click the button. However when i used IE, they gave me this error, http://imgur.com/kdxVOvd. – Bryan Jul 11 '13 at 01:46
  • I tried bringing it online in azure and run it on IE and i was given this weird error http://imgur.com/TnDJMy3 – Bryan Jul 11 '13 at 03:42
  • Can you try adding a new page, adding a single button and using the code above? You're running into a problem with some Ajax handler. – Chris Haas Jul 11 '13 at 13:50
  • You're right. However, why would there be an ajax handler problem? – Bryan Jul 12 '13 at 01:15
  • I don't know much about Microsoft's Ajax platform since I don't use it. But I believe that the button is executing in an Ajax callback which is supposed to return JSON (or possibly HTML). This method is returning a PDF and the Ajax library can't figure out what to do with it. The simplest solution would be to "un-Ajax" this button. Unfortunately I couldn't tell you how to do that. – Chris Haas Jul 12 '13 at 12:58
0

You might be able to do this with environment variables. That should let you always get the users documents (and downloads) folder regardless of where it's located.

How to get temporary folder for current user

How do I get and set Environment variables in C#?

Community
  • 1
  • 1
PlausibleSarge
  • 2,163
  • 1
  • 12
  • 12
  • I'm still somehow confused with how the codes work especially with the environment thing. – Bryan Jul 09 '13 at 08:55
0

You can use relative path instead of absolute path.

NanoNino
  • 33
  • 4
  • i have tried using this "~/Downloads" but it directs me to my IISExpress folder which isn't what i wanted. – Bryan Jul 09 '13 at 08:52
0

Saving to mobile device will likely be problematic using filestream, I would use localstorage instead, should work with both PC and mobile. Something to start with: http://msdn.microsoft.com/en-us/hh562072.aspx, otherwise just search for localstorage and webapp

BlackICE
  • 8,816
  • 3
  • 53
  • 91