0

I build two .Net applications for create pdf e-warranty. For create a pdf I use Web API 2.0 service integrated with OpenCart and everything is OK. For fill the pdf I create the second app - ASP.NET Web Forms and here is the problem with locking pdf file.

When once I open a file and fill some fields, then save the information to DB - everithing is OK. But if I want to add another information on the same pdf throw exception:

System.IO.IOException: The process cannot access the file '...\AllWarranties\2016\2\000077.pdf' because it is being used by another process.

This happen only when app is on server! When is on local machine there has no problem. I research and find the process w3wp.exe start when open the app. If I kill this process, then the pdf is unlocked. I set Idle Time-out for 1 min on the application poll, but this is not the solution.

And the question is: where is the problem with lock pdf? Is in the process or in me? Maybe I don't close some thing.

I use iTextSharp for fill the pdf.

Edit code with MemoryStream:

        string pdfDirectory = @"C:\Projects\Amco\EWarranty\EWarranty" + currentFilePath.FilePath;

        MemoryStream inputMemoryStream = new MemoryStream();

        using (FileStream fs = File.OpenRead(pdfDirectory))
        {
            inputMemoryStream.SetLength(fs.Length);
            fs.Read(inputMemoryStream.GetBuffer(), 0, (int)fs.Length);
            inputMemoryStream.Seek(0, SeekOrigin.Begin);
        }

        PdfReader pdfReader = new PdfReader(inputMemoryStream);

        using (Stream inputImageStream = new FileStream(@"C:\Projects\Amco\EWarranty\pechatAMCO.png", FileMode.Open, FileAccess.Read, FileShare.Read))
        using (MemoryStream outputStream = new MemoryStream())
        {
            using (PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream))
            {
                if (currentServiceMap.FailureNumber == 0)
                {
                    var pdfContentByte = pdfStamper.GetOverContent(3);

                    Image image = Image.GetInstance(inputImageStream);
                    image.ScaleToFit(150, 150);
                    image.SetAbsolutePosition(140, 425);
                    pdfContentByte.AddImage(image);
                }

                // Some other else if statements ...

                AcroFields pdfFormFields = pdfStamper.AcroFields;

                BaseFont cyrillicFont = BaseFont.CreateFont(@"C:\Windows\Fonts\Arial.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

                pdfFormFields.AddSubstitutionFont(cyrillicFont);

                // first fail
                if (txt_First_Adoption_Date.Text != "")
                {
                    pdfFormFields.SetField("firstAdoptionDate", txt_First_Adoption_Date.Text);
                }

                if (txt_First_Failure.Text != "")
                {
                    pdfFormFields.SetField("firstFailure", txt_First_Failure.Text);
                }

                if (txt_First_Return_Date.Text != "")
                {
                    pdfFormFields.SetField("firstReturnDate", txt_First_Return_Date.Text);
                }

                // Second, third and so on failds ...

                warrantyService.UpdateServiceMapByAdmin(CurrentSessions.warrantyNumber, txt_First_Adoption_Date.Text, txt_First_Failure.Text, "", txt_First_Return_Date.Text, txt_Second_Adoption_Date.Text, txt_Second_Failure.Text,
                                                            "", txt_Second_Return_Date.Text, txt_Third_Adoption_Date.Text, txt_Third_Failure.Text, "", txt_Third_Return_Date.Text, txt_Fourth_Adoption_Date.Text, txt_Fourth_Failure.Text,
                                                            "", txt_Fourth_Return_Date.Text, txt_Fifth_Adoption_Date.Text, txt_Fifth_Failure.Text, "", txt_Fifth_Return_Date.Text, (currentServiceMap.FailureNumber + 1));

                pdfStamper.FormFlattening = false;
            }

            byte[] pdfContent = outputStream.ToArray();

            File.WriteAllBytes(pdfDirectory, pdfContent);
        }

        pdfReader.Close();

        inputMemoryStream.Close();
dondomates
  • 55
  • 6

1 Answers1

2

You forgot this line:

pdfReader.Close();

When you do this, the file is released. If you omit this, the file can be released too, but it's hard to predict when. Apparently, the file is released quickly on your local machine; but it remains open for a longer time on your server.

I also don't understand how your code can work without closing the PdfStamper instance. Shouldn't you add this line before disposing pdfStamper:

pdfStamper.Close();

Maybe this line isn't strictly necessary (it would be necessary in the Java version of iText), but it doesn't hurt to add it.

Update: you are referring to a process called w3wp.exe. What is w3wp.exe?

An Internet Information Services (IIS) worker process is a windows process (w3wp.exe) which runs Web applications, and is responsible for handling requests sent to a Web Server for a specific application pool.

You have a file on disk that is released as far as iTextSharp is concerned, but that is locked by your web server (IIS). Why do you store the file on disk? Wouldn't you avoid this problem if you kept the file in memory? I don't know the complete process of your application, so I can't answer that part of the question.

Community
  • 1
  • 1
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • I store the file on the disk because this is the functionality that client wants. I don't know what you mean by kept the file in memory - maybe to store in session and then to disk, or what? Today I tested app and when make changes on one pdf, then go and make changes to another, then the first one is released and I can make change again. Thanks again for your help! – dondomates Feb 15 '16 at 15:00
  • 1
    You write the PDF to a `FileStream`. When I say "keep the file in memory", I mean that you can also write the PDF to a `MemoryStream`. Then you can use the bytes in memory to (1.) send them to the end user, (2.) load them into a `PdfReader` to change the file, (3.) store the bytes to disk in a file. – Bruno Lowagie Feb 15 '16 at 15:06
  • I change my code with `MemoryStream` but I don't know is that the right structured. However, now I get exeption on `File.WriteAllBytes(pdfDirectory, pdfContent);` when I go change fields for second time. Where I'm wrong? In some specific point or the all solution is wrong? – dondomates Feb 16 '16 at 12:11
  • 1
    Do you get the same exception? In any case: we have now established that the problem isn't related to iTextSharp: you can reproduce it simply by writing bytes to the same file twice. Why don't you post another question such as "Why doesn't IIS release files on the server?" With tags IIS, ASP, file. – Bruno Lowagie Feb 16 '16 at 12:18
  • Yes, exception is the same. I post another question, as adviced me. [Why doesn't IIS release files on the server?](http://stackoverflow.com/questions/35432935/why-doesnt-iis-release-files-on-the-server) – dondomates Feb 16 '16 at 12:44