So, i followed a tutorial to "upload" files to a local path using ASP.net core,
this is the code:
public IActionResult About(IList<IFormFile> files)
{
foreach (var file in files)
{
var filename = ContentDispositionHeaderValue
.Parse(file.ContentDisposition)
.FileName
.Trim('"');
filename = hostingEnv.WebRootPath + $#"\{filename}";
using (FileStream fs = System.IO.File.Create(filename))
{
file.CopyTo(fs);
fs.Flush();
}
}
return View();
}
I want to read the extended properties of a file (file metadata)like:
name,
author,
date posted,
etc
and to sort the files using this data, is there a way using Iformfile?
If you want to access more file metadata then the .NET framework provides ootb, I guess you need to use a third party library.
Otherwise you need to write your own COM wrapper to access those details.
See this link for a pure C# sample.
Here an example how to read the properties of a file:
Add Reference to Shell32.dll from the "Windows/System32" folder to
your project
List<string> arrHeaders = new List<string>();
List<Tuple<int, string, string>> attributes = new List<Tuple<int, string, string>>();
Shell32.Shell shell = new Shell32.Shell();
var strFileName = #"C:\Users\Admin\Google Drive\image.jpg";
Shell32.Folder objFolder = shell.NameSpace(System.IO.Path.GetDirectoryName(strFileName));
Shell32.FolderItem folderItem = objFolder.ParseName(System.IO.Path.GetFileName(strFileName));
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(null, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
// The attributes list below will contain a tuple with attribute index, name and value
// Once you know the index of the attribute you want to get,
// you can get it directly without looping, like this:
var Authors = objFolder.GetDetailsOf(folderItem, 20);
for (int i = 0; i < arrHeaders.Count; i++)
{
var attrName = arrHeaders[i];
var attrValue = objFolder.GetDetailsOf(folderItem, i);
var attrIdx = i;
attributes.Add(new Tuple<int, string, string>(attrIdx, attrName, attrValue));
Debug.WriteLine("{0}\t{1}: {2}", i, attrName, attrValue);
}
Console.ReadLine();
You can enrich this code to create custom classes and then do sorting depending on your needs.
There are many paid versions out there, but there is a free one called WindowsApiCodePack
For example accessing image metadata, I think it supports
ShellObject picture = ShellObject.FromParsingName(file);
var camera = picture.Properties.GetProperty(SystemProperties.System.Photo.CameraModel);
newItem.CameraModel = GetValue(camera, String.Empty, String.Empty);
var company = picture.Properties.GetProperty(SystemProperties.System.Photo.CameraManufacturer);
newItem.CameraMaker = GetValue(company, String.Empty, String.Empty);
Related
I am trying to create a process in .NET to convert a PDF and all it's pages + attachments to PNGs. I am evaluating libraries and came across PDFiumSharp but it is not working for me. Here is my code:
string Inputfile = "input.pdf";
string OutputFolder = "Output";
string fileName = Path.GetFileNameWithoutExtension(Inputfile);
using (PdfDocument doc = new PdfDocument(Inputfile))
{
for (int i = 0; i < doc.Pages.Count; i++)
{
var page = doc.Pages[i];
using (var bitmap = new PDFiumBitmap((int)page.Width, (int)page.Height, false))
{
page.Render(bitmap);
var targetFile = Path.Combine(OutputFolder, fileName + "_" + i + ".png");
bitmap.Save(targetFile);
}
}
}
When I run this code, I get this exception:
screenshot of exception
Does anyone know how to fix this? Also does PDFiumSharp support extracting PDF attachments? If not, does anyone have any other ideas on how to achieve my goal?
PDFium does not look like it supports extracting PDF attachments. If you want to achieve your goal, then you can take a look at another library that supports both extracting PDF attachments as well as converting PDFs to PNGs.
I am an employee of the LEADTOOLS PDF SDK which you can try out via these 2 nuget packages:
https://www.nuget.org/packages/Leadtools.Pdf/
https://www.nuget.org/packages/Leadtools.Document.Sdk/
Here is some code that will convert a PDF + all attachments in the PDF to separate PNGs in an output directory:
SetLicense();
cache = new FileCache { CacheDirectory = "cache" };
List<LEADDocument> documents = new List<LEADDocument>();
if (!Directory.Exists(OutputDir))
Directory.CreateDirectory(OutputDir);
using var document = DocumentFactory.LoadFromFile("attachments.pdf", new LoadDocumentOptions { Cache = cache, LoadAttachmentsMode = DocumentLoadAttachmentsMode.AsAttachments });
if (document.Pages.Count > 0)
documents.Add(document);
foreach (var attachment in document.Attachments)
documents.Add(document.LoadDocumentAttachment(new LoadAttachmentOptions { AttachmentNumber = attachment.AttachmentNumber }));
ConvertDocuments(documents, RasterImageFormat.Png);
And the ConvertDocuments method:
static void ConvertDocuments(IEnumerable<LEADDocument> documents, RasterImageFormat imageFormat)
{
using var converter = new DocumentConverter();
using var ocrEngine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD);
ocrEngine.Startup(null, null, null, null);
converter.SetOcrEngineInstance(ocrEngine, false);
converter.SetDocumentWriterInstance(new DocumentWriter());
foreach (var document in documents)
{
var name = string.IsNullOrEmpty(document.Name) ? "Attachment" : document.Name;
string outputFile = Path.Combine(OutputDir, $"{name}.{RasterCodecs.GetExtension(imageFormat)}");
int count = 1;
while (File.Exists(outputFile))
outputFile = Path.Combine(OutputDir, $"{name}({count++}).{RasterCodecs.GetExtension(imageFormat)}");
var jobData = new DocumentConverterJobData
{
Document = document,
Cache = cache,
DocumentFormat = DocumentFormat.User,
RasterImageFormat = imageFormat,
RasterImageBitsPerPixel = 0,
OutputDocumentFileName = outputFile,
};
var job = converter.Jobs.CreateJob(jobData);
converter.Jobs.RunJob(job);
}
}
I want to create a new pdf file using iTextSharp. All my code is working but the new file doesn't are ordered by page number.
Could you kindly let me know how to modify the following code to create new pdf file ordered by file name (page number)
foreach (var file in Directory.GetFiles(path))
{
reader = new PdfReader(file);
for (int i = 0; i < reader.NumberOfPages; i++)
{
page = pdf.GetImportedPage(reader, i + 1);
pdf.AddPage(page);
}
pdf.FreeReader(reader); reader.Close();
}
Folder contains 102 files. File name is Page_1, Page_2, Page_3 ...
I expected the output with pages ordered
Thank you very much in advance
Since you need to order numerically (i.e. Page_15 comes before Page_2 if you do it alphabetically), you need to extract that from the filename, for example:
// Needs some work but you get the idea
private int GetNumberFromFilename(string filename)
{
var baseName = Path.GetFileName(filename);
var parts = filename.Split('_','.');
if(int.TryParse(parts[1], out var number))
{
return number;
}
return 0;
}
Now you can get your ordered files like this:
var files = Directory.GetFiles(path)
.Where(f => Path.GetFileName(f).StartsWith("Page_")) //filter out non matching files
.OrderBy(GetNumberFromFilename);
I have a zip file that contains an exe, and I want to get the version number of the exe file without having to extract it physically.
I know how to read the contents of a zip file, and have code that will read a text file in it, but I can't find out how to get the version of an exe.
Add reference to Shell32.dll -library. Then you'll likely find what you are looking for with this:
Shell shell = new Shell();
var folder = shell.NameSpace( <path_to_your_zip> );
// Just get the names of the properties
List<string> arrHeaders = new List<string>();
for (int i = 0; i < short.MaxValue; i++)
{
string header = folder.GetDetailsOf(null, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
// Loop all files inside the zip and output their properties to console
foreach (Shell32.FolderItem2 item in folder.Items())
{
for (int i = 0; i < arrHeaders.Count; i++)
{
Console.WriteLine("{0}\t{1}: {2}", i, arrHeaders[i], folder.GetDetailsOf(item, i));
}
}
EDIT: Seems that this is not possible without actually extracting the file from the package. Something like this is fairly simple, but will take time in case the file is large and/or efficiently compressed.
Shell s = new Shell();
var folder = s.NameSpace( <path_to_your_zip> );
foreach (FolderItem2 item in folder.Items())
{
string oItemName = Path.GetFileName(item.Path);
try
{
string oTargetFile = Path.Combine(Path.GetTempPath(), oItemName);
if (File.Exists(oTargetFile))
File.Delete(oTargetFile);
Folder target = s.NameSpace(Path.GetTempPath());
target.CopyHere(item, 4);
var info = FileVersionInfo.GetVersionInfo(oTargetFile);
if (File.Exists(oTargetFile))
File.Delete(oTargetFile);
Console.WriteLine(oItemName + "'s version is: " + info.FileVersion);
}
catch (Exception e)
{
Console.WriteLine(oItemName + ": Unable to obtain version info.\n" + e.Message);
}
}
I have some problems with Telerik reports.
Feels like i have missed something...
I wanna create a list of reports, and then write them to ONE file.
But when i write it out i only get one page.
The writer writer over page 1 all foreach, so it just write one page.
But i want several pages... in this case 10.
Have tried write with FileStream, File and more...
Does anyone have a good idea?
public void WriteToFile()
{
string path = #"C:\";
string test = "test";
var report = new Report2();
var procceser = new ReportProcessor();
var list = new List<RenderingResult>();
for (int i = 0; i < 10; i++)
{
var res = procceser.RenderReport("PDF", report, null);
list.Add(res);
}
string filePath = Path.Combine(path, test);
var Writer = new BinaryWriter(File.Create(filePath));
foreach (var renderingResult in list)
{
Writer.Write(renderingResult.DocumentBytes);
}
Writer.Flush();
Writer.Close();
}
I am currently testing the google API. It seems promising, but I am stuck at a "simple" problem. I want to update an existing document with a local copy.
My idea was, download all google documents to a folder, using the doc-download. That works. At the next run, I check the dates, if a remote document is newer, grab it again. If the local document is newer, upload it, and replace the current online version.
I can't find a function to replace a document. There is a Upload(filename, doctitle) but this creates a new document. Does anybody know if this is possible and can point me in the correction direction. Do I have to dissect the atom feed (is the document content somewhere inside it..). The "download / change in word / upload" looked so nice :-)
Chris
And for anyone who is interested, its pretty simple and nice to use the API. Here is a short WPF example (without credentials, of course)
var settings = new RequestSettings("GoogleDocumentsSample", _credentials);
AllDocuments = new ObservableCollection<Document>();
settings.AutoPaging = true;
settings.PageSize = 10;
service = new DocumentsService("DocListUploader");
((GDataRequestFactory)service.RequestFactory).KeepAlive = false;
service.setUserCredentials(username, password);
//force the service to authenticate
var query = new DocumentsListQuery {NumberToRetrieve = 1};
service.Query(query);
var request = new DocumentsRequest(settings);
Feed<Document> feed = request.GetEverything();
// this takes care of paging the results in
foreach (Document entry in feed.Entries)
{
AllDocuments.Add(entry);
if (entry.Type == Document.DocumentType.Document)
{
var fI = new FileInfo(#"somepath" + entry.DocumentId + ".doc");
if (!fI.Exists || fI.LastWriteTime < entry.Updated)
{
Debug.WriteLine("Download doc " + entry.DocumentId);
var type = Document.DownloadType.doc;
Stream stream = request.Download(entry, type);
if (fI.Exists) fI.Delete();
Stream file = fI.OpenWrite();
int nBytes = 2048;
int count = 0;
Byte[] arr = new Byte[nBytes];
do
{
count = stream.Read(arr, 0, nBytes);
file.Write(arr, 0, count);
} while (count > 0);
file.Flush();
file.Close();
stream.Close();
fI.CreationTimeUtc = entry.Updated;
fI.LastWriteTimeUtc = entry.Updated;
}
else
{
if (entry.Updated == fI.LastWriteTime)
{
Debug.WriteLine("Document up to date " + entry.DocumentId);
}
else
{
Debug.WriteLine(String.Format("Local version newer {0} [LOCAL {1}] [REMOTE {2}]", entry.DocumentId, fI.LastWriteTimeUtc, entry.Updated));
service.UploadDocument(fI.FullName, entry.Title);
}
}
}
}
According to Docs API docs ;) you can replace the content of a document
http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html#UpdatingContent