I want to create a pdf file from Binary data. I looked around and found examples using iTextSharp by fetching data from the database.
But almost all of them show how to display in the browser. I want to create a file like
pdffromDB.pdf instead of displaying as shown below
doc.Close();
Response.BinaryWrite(MemStream.GetBuffer());
Response.End();
MemStream.Close();
I would really appreciate if you can direct me to an example that will allow me to create a real pdf file.
Thanks
Assuming your MemStream already contains all the bytes making up a valid PDF file, you should be able to convince the visitor's browser to prompt to save it as a file by adding the following statement before Response.BinaryWrite:
Response.AddHeader("Content-Disposition", "attachment; filename=Whatever.pdf")
As an aside, code after Response.End generally isn't executed: your MemStream will still be closed and disposed of just fine in this case due to going out of scope, but in general you should treat Response.End the same as Exit Sub, and code accordingly, e.g.
Using ms As New IO.MemoryStream
...
Response.End()
End Using
Related
Is it possible for the following code to produce NUL values within a text file?
var temp_str = "123456;1234567"
My.Computer.FileSystem.WriteAllText(Path & "stats.txt", temp_str, False)
It seems simple, but it writes quite often and I'm seeing several files that get accessed by the application that have Strings written to as:
When opening the file with Notepad++. Some other editors show just squares, and it seems like each character is represented by a block/NUL.
So far I've been unable to reproduce this on my test system. I just find the files on a COMX module's file system that's been running in the field and comes back faulty, but I've been seeing enough of these files to make it a problem that needs to be solved.
Does anyone have an idea to prevent this behaviour?
Hard to say what the problem is without more code, but try this if you want to replace the existing contents of the file:
Dim fileContent = "My UTF-8 file contents"
Using writer As IO.StreamWriter = IO.File.CreateText(fullPathIncludingExtension)
writer.Write(fileContent)
End Using
Or this if you want to append UTF-8 text:
Dim newLines = "My UTF-8 content to append"
Using writer As IO.StreamWriter = IO.File.AppendAllText(fullPathIncludingExtension)
writer.Write(fileContent)
End Using
If you want to append Unicode text, you must use a different constructor for StreamWriter:
Using writer As IO.StreamWriter = New IO.StreamWriter("full/path/to/file.txt", True, Text.Encoding.Unicode)
writer.Write(MyContentToAppend)
End Using
Note that the True argument to the constructor specifies that you want to append text.
I am upgrading some older iTextSharp code to the new iText 7 libraries. I am having a lot of trouble determining the proper way to merge 2 PDF MemoryStreams into one PDF MemoryStream that contains all the pages from both source PDF MemoryStreams. It seems simple and I think the code below is set up properly but the resulting PDF memory stream only contains the first file. The second PDF file is never present and never concatenated to the first.
I have found multiple ways documented on the Internet as the "proper" way to do the merge. The actual sample code with iText 7 seems to be unusually complex (in that is mixes multiple concepts into one sample repeatedly - as in doesn't reduce the concept to the simplest possible code), and seems to fail to demonstrate simple concepts. For instance, their PDFMerge documentation has no sample code at all in the documentation (nor does anything else I looked at in the class documentation). The examples they have online actually always mix merging from files (not MemoryStreams) with other concepts like adding page numbers or adding Table of Contents. So they never just show one concept and they never start with anything other than files. My PDFs are coming out of a database and we just need to merge them into one PDF memory stream and save it back out. My concern is that maybe I am not creating the MemoryStream properly when I initialize the PDFWriter. As none of their samples ever do anything but initial with an actual file, I was unable to confirm this was done properly. I also fully qualified all objects in the code because I want to leave the old iTextSharp code in place while I am upgrading to the new iText 7. This was done to make sure an iTextSharp object of the same name wasn't inadvertently being unknowingly used.
Also, in the interest of making the source as easy as possible to read I removed some of the declarations and initialization of objects being used. Everything was traced through and all values are fully loaded with proper values as you trace through the code. The only problem is that the second PDFMerge doesn't seem to do anything. I am assuming the problem is that I didn't prepare the PDF objects properly or that I have to do something special with the PDFWriter on the Destination PDF Document (p_pdfDocument) before the second PDF is written out with the PDFMerge object.
Dim p_bResult As Boolean = False
Dim p_bArray As Byte() = Nothing
Dim p_memStream As New System.IO.MemoryStream
Dim p_pdfWriter As New iText.Kernel.Pdf.PdfWriter(p_memStream)
Dim p_pdfDocument As New iText.Kernel.Pdf.PdfDocument(p_pdfWriter)
Dim p_pdf1Stream As New System.IO.MemoryStream(CType(p_cImage1.ImageFile, Byte()))
Dim p_pdf2Stream As New System.IO.MemoryStream(CType(p_cImage2.ImageFile, Byte()))
Dim p_pdf1Reader As New iText.Kernel.Pdf.PdfReader(p_pdf1Stream)
Dim p_pdf2Reader As New iText.Kernel.Pdf.PdfReader(p_pdf2Stream)
Dim p_pdf1Document As New iText.Kernel.Pdf.PdfDocument(p_pdf1Reader)
Dim p_pdf2Document As New iText.Kernel.Pdf.PdfDocument(p_pdf2Reader)
Dim p_pdfMerger As New iText.Kernel.Utils.PdfMerger(p_pdfDocument)
p_pdfMerger.Merge(p_pdf1Document, 1, p_pdf1Document.GetNumberOfPages())
p_pdfMerger.Merge(p_pdf2Document, 1, p_pdf2Document.GetNumberOfPages())
'Problem is here... the array only has the first PDF in it
'The second p_pdfMerger.Merge didn't seem to do anything
p_bArray = p_memStream.ToArray
p_pdf1Document.Close()
p_pdf2Document.Close()
p_pdfDocument.Close()
I expected the 2 source PDF MemoryStreams to be present in the destination MemoryStream but it only contains the first PDF in it.
Edit:
I changed the ending to...
p_pdfMerger.Merge(p_pdf1Document, 1, p_pdf1Document.GetNumberOfPages())
p_pdfMerger.Merge(p_pdf2Document, 1, p_pdf2Document.GetNumberOfPages())
p_cImage1.PageCount = p_pdfDocument.GetNumberOfPages()
p_pdfDocument.Close()
p_bArray = p_memStream.ToArray
p_pdf1Document.Close()
p_pdf2Document.Close()
Thing is that the p_pdfDocument.GetNumberOfPages() is correct but bytes are still just first PDF document when saved to database and viewed.
I tested your use case, condensing your code a bit, reading the input memory streams from files, and writing the output memory stream to a file as I don't have your database environment:
Using MemoryStream As New MemoryStream,
Pdf1MemoryStream As New MemoryStream(File.ReadAllBytes(MY_FIRST_PDF_FILE)),
Pdf2MemoryStream As New MemoryStream(File.ReadAllBytes(MY_SECOND_PDF_FILE))
Using PdfDocument As New PdfDocument(New PdfWriter(MemoryStream)),
Pdf1 As New PdfDocument(New PdfReader(Pdf1MemoryStream)),
Pdf2 As New PdfDocument(New PdfReader(Pdf2MemoryStream))
Dim Merger As New PdfMerger(PdfDocument)
Merger.Merge(Pdf1, 1, Pdf1.GetNumberOfPages)
Merger.Merge(Pdf2, 1, Pdf2.GetNumberOfPages)
End Using
Dim PdfBytes As Byte() = MemoryStream.ToArray()
Using FileStream As Stream = File.Create("TwoPdfsMergedInMemoryStream.pdf")
FileStream.Write(PdfBytes, 0, PdfBytes.Length)
End Using
End Using
As result I got the contents of both source files in TwoPdfsMergedInMemoryStream.pdf as it should be. Concerning your observation
Thing is that the p_pdfDocument.GetNumberOfPages() is correct but bytes are still just first PDF document when saved to database and viewed.
therefore, I would assume that p_bArray does contain a PDF with the contents of both your source PDFs but that there is an issue in saving to database or viewing.
To test this you could save the contents of the byte array to a file somewhere like I do above; then you can check what really is in the array.
I have a question about the following code. in order to prevent problems caused by file locking I came across the following code.
Dim OrignalBitmap As New Bitmap(Application.StartupPath & "\IMAGES\BACKGROUND_LARGE.jpg")
Dim CloneBitmap As New Bitmap(OrignalBitmap)
OrignalBitmap.Dispose()
Which works like a charm. Now I have all the images in place and I can still access them as a file without anything locking. It works so well for what I need that I was thinking if its possible to do this for file formats other than images such as Csv files which are then used in a datagridview as a bound table?
Usually it is enough to open a File like this, so that it will not block other programs to access and open it.
Dim path1 As String = "C:\temp\temp.csv"
Using fs As FileStream = File.Open(path1, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
' Do something with filestream
End Using
this will prevent even huge files to open without blocking access
you should check https://learn.microsoft.com/de-de/dotnet/api/system.io.file.open?view=netframework-4.8
I'm attempting to use OpenXML for opening a word document, and after modifications, return a modified version to the user as a downloadable file. As for the downloadable portion of this, I have that covered, in that, I modify my response to simply return a word document. But, what I am having a problem with is successfully opening and modifying a word document. While I am able to provide a document to download, the file is consistently "corrupt" when I open it.
I have an extremely simple snippet that is still returning a corrupt word document. It's almost as though the file becomes corrupt the very moment I open it (since I've removed all of the modifications from this snippet).
Private Function GenerateExportWithTemplate() As MemoryStream
Dim template As Byte() = System.IO.File.ReadAllBytes(strTemplateFileName)
Using ms As New MemoryStream()
ms.Write(template, 0, template.Length)
Using doc As WordprocessingDocument = WordprocessingDocument.Open(ms, True)
'Code to modify word document.
End Using
Return ms
End Using
End Function
I don't believe I fully understand what is happening in the snippet above. Any explanation in why I am receiving a corrupt file would be greatly appreciated.
How do I successfully open and modify a WordProcessingDocument from a template file, and return as a memory stream? While there are a million examples of how to open a file and make modifications, I have yet to find one that is successful. Meaning, the file is corrupt every time. How do I do this without receiving a corrupt word document as the result?
On a button click I have the following code to write what Is in my textboxes.
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter("C:/Users/Nick/Documents/Dra.txt", False)
file.WriteLine(NameBasic)
file.WriteLine(LastBasic)
file.WriteLine(PhoneBasic)
file.WriteLine(NameEmer1)
On my form load, I load what is in the notepad from what was written, It is saying It is already being used(the file) which is true, how can I have two different functions(write, and read) manipulating the same file with out this error?
The process cannot access the file 'C:\Users\Nick\Documents\Dra.txt' because it is being used by another process.
And here is the code for my onformload
Dim read As System.IO.StreamReader
read = My.Computer.FileSystem.OpenTextFileReader("C:/Users/Nick/Documents/Dra.txt")
lblNameBasic.Text = read.ReadLine
I am sort of stuck on this problem, thank you
You need to close the file when you are done writing to it.
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter("C:/Users/Nick/Documents/Dra.txt", False)
file.WriteLine(NameBasic)
file.WriteLine(LastBasic)
file.WriteLine(PhoneBasic)
file.WriteLine(NameEmer1)
file.Close()
To answer your question:
how can I have two different functions(write, and read) manipulating the same file with out this error?
If you really want to simultaneously read and write to the same file from two processes, you need to open the file with the FileShare.ReadWrite option. The My.Computer.FileSystem methods don't do that.¹
However, I suspect that you don't really wan't to do that. I suspect that you want to write and, after you are finished writing, you want to read. In that case, just closing the file after using it will suffice. The easiest way to do that is to use the Using statement:
Using file = My.Computer.FileSystem.OpenTextFileWriter(...)
file.WriteLine(...)
file.WriteLine(...)
...
End Using
This ensures that the file will be closed properly as soon as the Using block is left (either by normal execution or by an exception). In fact, it is good practice to wrap use of every object whose class implements IDisposable (such as StreamWriter) in a Using statement.
¹ According to the reference source, OpenTextFileWriter creates a New IO.StreamWriter(file, append, encoding), which in turn creates a new FileStream(..., FileShare.Read, ...).