Use MergeFields to manipulate a word document with stream - c#

This is the old code where copy to a local path, but now i need to save the file on SharePoint. How can i use stream with it and write the stream to file.
File.Copy(oTemplatePath, destinationPath, true);
using (WordprocessingDocument document = WordprocessingDocument.Open(destinationPath, true))
{
document.GetMergeFields("reference_number").ReplaceWithText(refrenceNumber);
document.MainDocumentPart.Document.Save();
for (int i = 0; i < newDoc.jsonFields.Count; i++)
{
if (newDoc.jsonFields[i].type == "date")
{
document.GetMergeFields(newDoc.jsonFields[i].controlName).ReplaceWithText(DateTime.Parse(newDoc.jsonFields[i].data).ToShortDateString());
document.MainDocumentPart.Document.Save();
}
else
{
document.GetMergeFields(newDoc.jsonFields[i].controlName).ReplaceWithText(newDoc.jsonFields[i].data);
document.MainDocumentPart.Document.Save();
}
}
//document.GetMergeFields(newDoc.jsonFields[i].controlName).ReplaceWithText(newDoc.jsonFields[i].data);
//document.MainDocumentPart.Document.Save();
}

You can save to local temp folder
string tempDocx = Path.Combine(Path.GetTempPath(), fileName);
logger.Trace($"Creating Word document {tempDocx}");
File.Delete(tempDocx);
File.Copy("Template.docx", tempDocx);
Then upload to SharePoint, here using a FileStream
using (IO.FileStream fs = new IO.FileStream(tempDocx, IO.FileMode.Open))
{
List documentsList = clientContext.Web.Lists.GetByTitle(libTitle);
clientContext.Load(documentsList.RootFolder);
clientContext.ExecuteQuery();
var fileCreationInformation = new FileCreationInformation();
//Assign to content byte[] i.e. documentStream
fileCreationInformation.ContentStream = fs;
//Allow owerwrite of document
fileCreationInformation.Overwrite = true;
//Upload URL
fileCreationInformation.Url = documentsList.RootFolder.ServerRelativeUrl + "/" + IO.Path.GetFileName(tempDocx);
uploadFile = documentsList.RootFolder.Files.Add(fileCreationInformation);
clientContext.Load(uploadFile);
clientContext.ExecuteQuery();
}

Related

C# - Trying to grab and save a pdf into my database

In my C# application, I am trying to make it able to pull a pdf and save it, so that end users can press a button and pull up that pdf while they are in the application. But when I copy the content to the filestream it makes the pdf but it is just blank with nothing from the original pdf. What am I doing wrong?
The pdf's could also have pictures on them, and I don't think the way I'm doing it would allow those to be brought over.
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
bool? response = openFileDialog.ShowDialog();
var fileContent = string.Empty;
var filestream = openFileDialog.OpenFile();
using (StreamReader reader = new StreamReader(filestream))
{
fileContent = reader.ReadToEnd();
}
// make folder path
string FolderPath = "ProjectPDFs\\";
string RootPath = "X:\\Vents-US Inventory";
DirectoryInfo FolderDir = new DirectoryInfo(Path.Combine(RootPath, FolderPath));
Directory.CreateDirectory(FolderDir.ToString());
string filePath = "";
string FileName = openFileDialog.SafeFileName;
if (fileContent.Length > 0)
{
filePath = Path.Combine(FolderDir.ToString(), FileName);
using (Stream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
byte[] bytestream = Encoding.UTF8.GetBytes(fileContent);
Stream stream = new MemoryStream(bytestream);
stream.CopyTo(fileStream);
}
}

Creating Zip file with multiple entries in C# .net

I created the functionality to get documents from blob storage and then add them to a zip file for download.
[HttpPost]
public FileContentResult DownloadDocumentsByDocIDZIP(List<int> documentIDs)
{
List<Document> docs = new List<Document>();
foreach (int doc in documentIDs)
{
if (doc != 0)
{
Document document = documentService.GetDocumentByID(doc, false);
docs.Add(document);
}
}
MemoryStream outms = new MemoryStream();
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
Stream str = entry.Open();
MemoryStream ms = new MemoryStream(unzipped);
ms.CopyTo(str);
}
}
outms.Seek(0, SeekOrigin.Begin);
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;
}
When I hit the function via ajax, It fails at
ZipArchiveEntry entry = zar.CreateEntry(name);
I'm given the exception,
System.IO.IOException: 'Entries cannot be created while previously created entries are still open.'
So I added str.close()
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
Stream str = entry.Open();
MemoryStream ms = new MemoryStream(unzipped);
ms.CopyTo(str);
str.Close();
}
}
outms.Seek(0, SeekOrigin.Begin);
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;
Now it creates the file but when you try to unzip it after download.
It gives me an error in WinZip. Error: unable to seek to beginning of Central Directory.
Can someone please assist I have no idea what I'm doing wrong?
you have to dispose the Stream before add new stream to zip but the real problem is that you call Seek on stream, try the following code:
using (ZipArchive zar = new ZipArchive(outms, ZipArchiveMode.Create, false))
{
foreach (Document docu in docs)
{
if (docu != null)
{
byte[] documentdata = documentService.DownloadDocumentData(docu.DocumentID);
string name = docu.DocumentNiceName ?? docu.DocumentFileName;
byte[] unzipped = documentdata;
ZipArchiveEntry entry = zar.CreateEntry(name);
using (Stream str = entry.Open())
{
str.Write(unzipped);
}
}
}
//outms.Seek(0, SeekOrigin.Begin); //This causes "Error: unable to seek to beginning of Central Directory."
}
var outdata = outms.ToArray();
var result = File(outdata, "application/zip", "documents.zip");
return result;

iText7 pdf to blob c#

Using c# and iText7 I need to modify an existing PDF and save it to blob storage.
I have a console app that does exactly what I need using the file system:
PdfReader reader = new PdfReader(source);
PdfWriter writer = new PdfWriter(destination2);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
fields = form.GetFormFields();
fields.TryGetValue("header", out PdfFormField cl);
var type = cl.GetType();
cl.SetValue("This is a header");
pdfDoc.Close();
This works just fine. However I can not figure out how to do the same thing pulling the PDF from blob storage and sending the new one to blob storage
IDictionary<string, PdfFormField> fields;
MemoryStream outStream = new MemoryStream();
var pdfTemplate = _blobStorageService.GetBlob("mycontainer", "TestPDF.pdf");
PdfReader reader = new PdfReader(pdfTemplate);
PdfWriter writer = new PdfWriter(outStream);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
fields = form.GetFormFields();
fields.TryGetValue("header", out PdfFormField cl);
cl.SetValue("This is a header");
pdfDoc.Close();
outStream.Position = 0;
_blobStorageService.UploadBlobAsync("mycontainer", **THIS IS THE ISSUE**, "newpdf.pdf");
I think I need to get pdfDoc as a byte array. Outstream is incorrect, it is only has a length of 15
The code below shows how to read a PDF from a file into a byte[] and also how to modify a PDF that's stored as a byte[].
Download and install NuGet package: iText7
In Solution Explorer, right-click <project name> and select Manage NuGet Packages...
Click Browse
In the search box type: iText7
Select iText7
Select desired version
Click Install
Add the following using statements:
using System.IO;
using iText.Kernel.Pdf;
using iText.Forms;
using iText.Forms.Fields;
Get PDF as byte[] (GetPdfBytes):
public static Task<byte[]> GetPdfBytes(string pdfFilename)
{
byte[] pdfBytes = null;
using (PdfReader reader = new PdfReader(pdfFilename))
{
using (MemoryStream msPdfWriter = new MemoryStream())
{
using (PdfWriter writer = new PdfWriter(msPdfWriter))
{
using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
{
//don't close underlying streams when PdfDocument is closed
pdfDoc.SetCloseReader(false);
pdfDoc.SetCloseWriter(false);
//close
pdfDoc.Close();
//set value
msPdfWriter.Position = 0;
//convert to byte[]
pdfBytes = msPdfWriter.ToArray();
}
}
}
}
return Task.FromResult(pdfBytes);
}
Usage:
byte[] pdfBytes = null;
string filename = string.Empty;
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "PDF File (*.pdf)|*.pdf";
if (ofd.ShowDialog() == DialogResult.OK)
{
//get PDF as byte[]
var tResult = GetPdfBytes(ofd.FileName);
pdfBytes = tResult.Result;
//For testing, write back to file so we can ensure that the PDF file opens properly
//create a new filename
filename = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName) + " - Test.pdf";
filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(ofd.FileName), filename);
//save to file
File.WriteAllBytes(filename, pdfBytes);
System.Diagnostics.Debug.WriteLine("Saved as '" + filename + "'");
}
Modify PDF that's stored in a byte[] (ModifyPdf)
public static Task<byte[]> ModifyPdf(byte[] pdfBytes)
{
byte[] modifiedPdfBytes = null;
using (MemoryStream ms = new MemoryStream(pdfBytes))
{
using (PdfReader reader = new PdfReader(ms))
{
using (MemoryStream msPdfWriter = new MemoryStream())
{
using (PdfWriter writer = new PdfWriter(msPdfWriter))
{
using (PdfDocument pdfDoc = new PdfDocument(reader, writer))
{
//don't close underlying streams when PdfDocument is closed
pdfDoc.SetCloseReader(false);
pdfDoc.SetCloseWriter(false);
//get AcroForm from document
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdfDoc, true);
//get form fields
IDictionary<string, PdfFormField> fields = form.GetFormFields();
//for testing, show all fields
foreach (KeyValuePair<string, PdfFormField> kvp in fields)
{
System.Diagnostics.Debug.WriteLine("Key: '" + kvp.Key + "' Value: '" + kvp.Value + "'");
}
PdfFormField cl = null;
//get specified field
fields.TryGetValue("1 Employee name", out cl);
//set value for specified field
cl.SetValue("John Doe");
//close PdfDocument
pdfDoc.Close();
//set value
msPdfWriter.Position = 0;
//convert to byte[]
modifiedPdfBytes = msPdfWriter.ToArray();
}
}
}
}
}
return Task.FromResult(modifiedPdfBytes);
}
Usage:
byte[] pdfBytes = null;
string filename = string.Empty;
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "PDF File (*.pdf)|*.pdf";
if (ofd.ShowDialog() == DialogResult.OK)
{
//get PDF as byte[]
var tResult = GetPdfBytes(ofd.FileName);
pdfBytes = tResult.Result;
//modify PDF
pdfBytes = await ModifyPdf(pdfBytes);
//create a new filename
filename = System.IO.Path.GetFileNameWithoutExtension(ofd.FileName) + " - TestModified.pdf";
filename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(ofd.FileName), filename);
//save to file
File.WriteAllBytes(filename, pdfBytes);
System.Diagnostics.Debug.WriteLine("Saved as '" + filename + "'");
}
The code below is adapted from Sample01b_HelloWorldAsync.cs and is untested.
Download and install NuGet package: Azure.Storage.Blobs
Add the following using statement:
using Azure.Storage.Blobs;
DownloadPdf:
public static async Task<byte[]> DownloadPdf(string connectionString, string blobContainerName, string blobName)
{
byte[] pdfBytes = null;
using (MemoryStream ms = new MemoryStream())
{
// Get a reference to the container and then create it
BlobContainerClient container = new BlobContainerClient(connectionString, blobContainerName);
Azure.Response<Azure.Storage.Blobs.Models.BlobContainerInfo> responseCA = await container.CreateAsync();
// Get a reference to the blob
BlobClient blob = container.GetBlobClient(blobName);
// Download the blob's contents and save it to a file
Azure.Response responseDTA = await blob.DownloadToAsync(ms);
//set value
ms.Position = 0;
//convert to byte[]
pdfBytes = ms.ToArray();
}
return pdfBytes;
}
UploadPdf:
public static async Task<Azure.Response<Azure.Storage.Blobs.Models.BlobContentInfo>> UpdloadPdf(byte[] pdfBytes, string connectionString, string blobContainerName, string blobName)
{
Azure.Response<Azure.Storage.Blobs.Models.BlobContentInfo> result = null;
using (MemoryStream ms = new MemoryStream(pdfBytes))
{
//this statement may not be necessary
ms.Position = 0;
// Get a reference to the container and then create it
BlobContainerClient container = new BlobContainerClient(connectionString, blobContainerName);
await container.CreateAsync();
// Get a reference to the blob
BlobClient blob = container.GetBlobClient(blobName);
//upload
result = await blob.UploadAsync(ms);
}
return result;
}
Here's a PDF file for testing.

How can save pdf genrated file to project folder using asp.net C#?

I have generated a pdf file from html and now I need to save it to a folder in my project.
I am able to get the generated pdf to download locally but when I send it to the file folder it gets corrupted and will not open.
public void CreateHTML(ComplaintIntakeData cd)
{
string formHtml = "<table class=\"MsoNormal\">";
string complaintTypeHtml = PCSUtilities.GetComplaintTypeHTML(cd);
string providerHtml = "";
if (cd.Providers != null && cd.Providers.Count > 0)
{
providerHtml = PCSUtilities.GetProviderHTML(cd);
}
string facilityHtml = PCSUtilities.GetFacilityHTML(cd);
string anonymousHtml = PCSUtilities.GetAnonymousHTML(cd);
string contactHtml = PCSUtilities.GetContactHTML(cd);
string patientHtml = PCSUtilities.GetPatientHTML(cd);
string detailsHtml = PCSUtilities.GetComplaintDetailsHTML(cd);
formHtml = formHtml + complaintTypeHtml + providerHtml + facilityHtml + anonymousHtml + contactHtml + patientHtml + detailsHtml + "</table>";
formHtml = formHtml.Replace("''", "\"");
// Load HTML template for letter and replace template fields with provider data
string htmlContent = File.ReadAllText(Server.MapPath("~/ComplaintIntakeForm.html"));
htmlContent = htmlContent.Replace("<%ComplaintInformation%>", formHtml);
string fileName = "ComplaintIntakeFile_" + cd.ComplaintGuid.ToString() +".pdf";
using (MemoryStream memStream = new MemoryStream())
{
try
{
// Load up a new PDF doc.
iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(PageSize.LETTER);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, memStream);
// writer.CompressionLevel = PdfStream.NO_COMPRESSION;
// Make document tagged PDFVERSION_1_7
writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
writer.SetTagged();
// Set document metadata
writer.ViewerPreferences = PdfWriter.DisplayDocTitle;
pdfDoc.AddLanguage("en-US");
pdfDoc.AddTitle("Complaint Intake Form");
writer.CreateXmpMetadata();
pdfDoc.Open();
var tagProcessors = (DefaultTagProcessorFactory)Tags.GetHtmlTagProcessorFactory();
//tagProcessors.RemoveProcessor(HTML.Tag.IMG);
//tagProcessors.AddProcessor(HTML.Tag.IMG, new CustomImageTagProcessor());
var cssFiles = new CssFilesImpl();
cssFiles.Add(XMLWorkerHelper.GetInstance().GetDefaultCSS());
var cssResolver = new StyleAttrCSSResolver(cssFiles);
var charset = Encoding.UTF8;
var context = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider()));
context.SetAcceptUnknown(true).AutoBookmark(true).SetTagFactory(tagProcessors);
var htmlPipeline = new HtmlPipeline(context, new PdfWriterPipeline(pdfDoc, writer));
var cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
var worker = new XMLWorker(cssPipeline, true);
var xmlParser = new XMLParser(true, worker, charset);
try
{
using (var sr = new StringReader(htmlContent))
{
xmlParser.Parse(sr);
// xmlParser.Flush();
}
}
catch (Exception e)
{
Response.Write(e.Message);
}
pdfDoc.Close();
//writer.Close();
///this creates a pdf download.
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.OutputStream.Write(memStream.GetBuffer(), 0, memStream.GetBuffer().Length);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("The following error occurred:\n" + ex.ToString());
}
}
}
when I add the following to create the file. The file is created but it is corrupted and cannot open as a pdf
using (FileStream file = new FileStream(Server.MapPath("~/tempFiles/") + fileName, FileMode.CreateNew))
{
byte[] bytes = new byte[memStream.Length];
memStream.Read(bytes, 0, memStream.Length);
file.Write(bytes, 0, bytes.Length);
}
I think this answer is relevant:
Copy MemoryStream to FileStream and save the file?
Your two code snippets use both memStream and memString and without seeing all the code in context, I'm guessing. Assuming memStream is a Stream that contains the contents of your PDF, you can write it to a file like this:
using (FileStream file = new FileStream(Server.MapPath("~/tempFiles/") + fileName, FileMode.CreateNew))
{
memStream.Position = 0;
memStream.CopyTo(file);
}
I wound up moving the new FileStream call into the PdfWriter.GetInstance method in place of the memStream variable. And was able to get rid of the using filestream code all together.
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, new FileStream(Server.MapPath(path)+"/" + fileName, FileMode.CreateNew));

How to upload a file to a document library given a HttpPostedFile

I have a HttpPostedFile object and after the file gets uploaded locally onto the server, i want to move that temp file into a document library in sharepoint. Here is my code:
private void UploadWholeFile(HttpContext context, List<FilesStatus> statuses) {
for (int i = 0; i < context.Request.Files.Count; i++) {
HttpPostedFile file = context.Request.Files[i];
file.SaveAs(ingestPath + Path.GetFileName(file.FileName));
string fileName = Path.GetFileName(file.FileName);
}
Can anyone give me some example code for this? I have found a tutorial for Streams, but not quite sure if it would work the same in my situation
Replace the two lines starting with file.SaveAs with the following:
var myDocumentLibrary = SPContext.Current.Web.Folders["MyDocumentLibrary"];
var myFile = myDocumentLibrary.Files.Add(file.Name, file.FileContent, true);
I have a code sample for you that comes in parts:
Here is code that gets the Files content into a byte array buffer:
var file = (HttpPostedFileBase)Request.Files[0];
var buffer = new byte[file.ContentLength];
file.InputStream.Read(buffer, 0, file.ContentLength);
var root = HttpContext.Current.Server.MapPath(#"~/_temp");
var temp_file_name = "somefilename";
var path = Path.Combine(root, temp_file_name);
using (var fs = new FileStream(path, FileMode.Create))
{
using (var br = new BinaryWriter(fs))
{
br.Write(buffer);
}
}

Categories

Resources