Azure Function couldnt find document openXML - c#

I am new in Azure Functions and i am try to discover some features of it.
So i created function blob trigger, added references of OpenXML sdk in project.json
"frameworks": {
"net46":{
"dependencies": {
"WindowsAzure.Storage": "7.0.0" ,
"Open-XML-SDK" : "2.7.2",
"DocumentFormat.OpenXml" : "2.8.1"
And in run.csx i added next code
using System;
using System.IO;
using Microsoft.Azure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml;
public static void Run (Stream myBlob, string name, TraceWriter log)
{
// *While we upload a blob, function start to execute*
StreamReader reader = new StreamReader(myBlob);
string S = reader.ReadToEnd();
int numberofSlides = CountSlides(S);
log.Info($"Number of slides = {numberofSlides}");
}
// *here, using XML sdk we open our presentation without using Office*
public static int CountSlides(string presentationFile)
{
using (PresentationDocument presentationDocument =PresentationDocument.Open(presentationFile, false))
{
return CountSlides(presentationDocument);
}
}
public static int CountSlides(PresentationDocument presentationDocument)
{
if (presentationDocument == null)
{
throw new ArgumentNullException("presentationDocument");
}
int slidesCount = 0;
PresentationPart presentationPart = presentationDocument.PresentationPart;
if (presentationPart != null)
{
slidesCount = presentationPart.SlideParts.Count();
}
return slidesCount;
}
The problem is while i upload a .pptx , i have error in log
Exception while executing function: Functions.BlobTriggerCSharp1. mscorlib: Exception has been thrown by the target of an invocation. DocumentFormat.OpenXml: Could not find document.
I upload a file .pptx using Microsoft Azure Storage Explorer and I can not understand why i have an error.

You are using the following method:
public static PresentationDocument Open(
string path,
bool isEditable
)
The first parameter it accepts is path but you pass the file contents in there. It tries to find this weird file path and throws exception.
Try using the Stream overload.

Related

Convet Html string to PDF in Dotnet 7 without warnings

I want to convert an html string into a byte[] pdf and send it as a file for download. But all the libraries I see either have dependency issues or won't work and give errors like "System.Drawing.Common is not supported on this platform.".
I'm working on Ubuntu
Dotnet version 7.0.102
Some packages give warning like -
"Package 'PDFsharp 1.32.3057' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8, .NETFramework,Version=v4.8.1' instead of the project target framework 'net7.0'. This package may not be fully compatible with your project."
this stops me from being able to use hot reload feature when using dotnet watch, it asks me to restart the server on every change.
You can use the iTextSharp library for this.
Please refer to the below code snippet for your reference :
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;
namespace HTMLToPDFExample
{
class Program
{
static void Main(string[] args)
{
// Your string HTML here
string html = #"<html><body>
<h1>Example HTML to PDF Conversion</h1>
<p>This is an example of how to convert an HTML string to a PDF document.</p>
</body></html>";
string pdfFile = "example.pdf";
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4))
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
using (var sr = new StringReader(html))
{
var htmlContext = new HTMLWorker(doc);
htmlContext.Parse(sr);
}
doc.Close();
}
}
File.WriteAllBytes(pdfFile, ms.ToArray());
}
}
}
}

WinForms how to open file in resources folder

I am new in WinForms technology. I am using .NET Framework 4.8 , Microsoft Visual Studio 2019. I put file in Resources folder.
I tried something like this
using DevExpress.XtraBars;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
Console.WriteLine(System.AppDomain.CurrentDomain.BaseDirectory);
Process.Start(".../B01-DN_01_Summary.xlsx");
}
}
}
please guide me finish it.
I do this in one of my applications to open a XLSX file that is an embedded resource in my application
private void buttonOpenTemplate_Click(object sender, EventArgs e)
{
byte[] templateFile = Properties.Resources._01__So_du_tai_khoan; // This is your Excel document in the application Resources
string tempPath = $"{Path.GetTempFileName()}.xlsx";
using (MemoryStream ms = new MemoryStream(templateFile))
{
using(FileStream fs = new FileStream(tempPath, FileMode.OpenOrCreate))
{
ms.WriteTo(fs);
fs.Close();
}
ms.Close();
}
Process.Start(tempPath);
}
This requires a reference to System.IO for access to the MemoryStream and FileStream classes.
You are currently only outputting the base directory. Along with that, you're only looking for files within that base directory. Execution happens from the base directory, so your program is looking for ..\Path\to\exe\B01-DN_01_Summary.xlsx when it should be looking for ..\Path\to\exe\Resources\FilesHere\ImportExcel\B01-DN_01_Summary.xlsx
To note: embedding resources files into your application is not recommend. It's preferable to instead store their locations and allow the application to traverse your directories to find the specified file locations.
Here's an adapted version you can try:
You will need to make sure that the Copy to Output Directory property for you desire file is set to "Copy Always" or "Copy if Newer". This will ensure the directory path is created in your output directory.
namespace accwf
{
public partial class NhapSoDu : DevExpress.XtraBars.Ribbon.RibbonForm
{
public NhapSoDu()
{
InitializeComponent();
}
private void simpleButton1_Click(object sender, EventArgs e)
{
string resourcePath = System.IO.File.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Resources\\FilesHere\\ImportExcel\\B01-DN_01_Summary.xlsx")
if (File.Exists(resourcePath))
{
MessageBox.Show("Exists");
}
else
{
MessageBox.Show("Doesn't Exist");
}
Process.Start(resourcePath);
}
}
}
This is an example of how I get PDF file documentation for a help menu I have:
public void MyMethod()
{
// helpMenuPath is a global var set to something like: Area/MyApp/Resources/
string filePath = helpMenuPath;
string[] fileNames = new string[0]; // Initialize the variable with length of 0. Directory.GetFiles() will allow for this length to be overwritten
// Try/Catch in case bad dir
try
{
fileNames = Directory.GetFiles(filePath);
}
catch (IOException ioe)
{
// error catch for if bad dir
MessageBox.Show($"Error in getting files: {ioe.Message}");
}
// Do something with files ...
}

Custom log4net azure blob appender stops logging when a file reaches 5.4MB

I am using the appender below to pipe our log messages to Azure with Log4Net.
Everything works fine, until the blob file reaches the size of 5.4MB. From than, no logs are appended to the log file anymore.
What is causing this? And how can I solve this?
namespace Digicreate.Core.Infrastructure.Logging
{
using System;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using log4net.Appender;
using log4net.Config;
using log4net.Core;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
// ReSharper disable once UnusedMember.Global
// justification: used in log4net configuration file
public class AzureBlobTxtFileAppender : BufferingAppenderSkeleton
{
private CloudStorageAccount _account;
...removed unimportant code...
protected override void SendBuffer(LoggingEvent[] events)
{
var appendBlobReference = _cloudBlobContainer.GetAppendBlobReference(Filename(DirectoryName));
if (!appendBlobReference.Exists())
{
appendBlobReference.CreateOrReplace();
}
Parallel.ForEach(events, ProcessEvent);
}
private static string Filename(string directoryName)
{
return $"{directoryName}/{DateTime.Today.ToString("yyyy_MM_dd", DateTimeFormatInfo.InvariantInfo)}.log.txt";
}
private void ProcessEvent(LoggingEvent loggingEvent)
{
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8, 1024, true))
{
Layout.Format(streamWriter, loggingEvent);
streamWriter.Flush();
}
memoryStream.Position = 0;
_cloudBlobContainer
.GetAppendBlobReference(Filename(DirectoryName))
.AppendBlock(memoryStream);
}
}
}
}
According to Append Block documentation you might be hittin 50,000 block limit for a blob. Make sure to check for number of committed blocks before committing to the Blob using:
var blockCount = _cloudBlobContainer.GetAppendBlobReference(Filename(DirectoryName))
.Properties
.AppendBlobCommittedBlockCount;
and make sure it is not more than 50000.

I want to copy a document from my tfs project to my local storage using c#

I have some documents in my TFS project,I want to create a console application that reads the documents from TFS and copy the file to my local storage, any idea?
Check the code in this article, which works for you:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string teamProjectCollectionUrl = "http://YourTfsUrl:8080/tfs/YourTeamProjectCollection";
string filePath = #"C:\project\myfile.cs";
// Get the version control server
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(teamProjectCollectionUrl));
VersionControlServer versionControlServer = teamProjectCollection.GetService<VersionControlServer>();
// Get the latest Item for filePath
Item item = versionControlServer.GetItem(filePath, VersionSpec.Latest);
// Download and display content to console
string fileString = string.Empty;
using (Stream stream = item.DownloadFile())
{
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
// Use StreamReader to read MemoryStream created from byte array
using (StreamReader streamReader = new StreamReader(new MemoryStream(memoryStream.ToArray())))
{
fileString = streamReader.ReadToEnd();
}
}
}
Console.WriteLine(fileString);
Console.ReadLine();
}
}
}
By the way, you can also use tf get command to get or download a specified version of one or more files or folders from TFS to the workspace, which is an easy way.

How can I return a stream rather than writing to disk?

I am using OpenXML SDK.
The OpenXML SDK creates a method called CreatePackage as such:
public void CreatePackage(string filePath)
{
using (SpreadsheetDocument package = SpreadsheetDocument.Create(filePath, SpreadsheetDocumentType.Workbook))
{
CreateParts(package);
}
}
I call it from my program as follows which will create the Excel file to a given path:
gc.CreatePackage(excelFilePath);
Process.Start(_excelFilePath);
I am not sure how to tweak the code such that it gives back a Stream which shows the Excel file vs having it create the file on disk.
According to the documentation for SpreadsheetDocument.Create there are multiple overloads, one of which takes a Stream.
so change your code to:
public void CreatePackage(Stream stream)
{
using (SpreadsheetDocument package = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook))
{
CreateParts(package);
}
}
And then call it with any valid Stream, for example:
using(var memoryStream = new MemoryStream())
{
CreatePackage(memoryStream);
// do something with memoryStream
}

Categories

Resources