Whenver I upload a file I want to have it automatically converted into
.pdf (I am doing that using NuGet). The thing is the upload scheme is done using
relative pathing. I do now know what to put into this parantheses:
var wordDocument = appWord.Documents.Open(uploadedFile);
This gives a null exception; saying that the file has NOT been found.
NOTE that the uploading code , without the conversion part, is working flawlessly.
What should I replace uploadedFile with in order to work? I will leave my
realtive path mapping code below so you can see everything that I have done
in order to better help you (and me as well) with what should be put into
that parantheses in order to work? Thank you so much!
public IActionResult Index1()
{
// Get files from the server
var model = new FilesViewModel();
foreach (var item in Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "upload")))
{
model.Files.Add(
new FileDetails { Name = System.IO.Path.GetFileName(item), Path = item });
}
return View(model);
}
[HttpPost]
public IActionResult Index1(IFormFile[] files)
{
// Iterate each files
foreach (var file in files)
{
// Get the file name from the browser
var fileName = System.IO.Path.GetFileName(file.FileName);
// Get file path to be uploaded
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "upload", fileName);
// Check If file with same name exists and delete it
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
}
// Create a new local file and copy contents of uploaded file
using (var localFile = System.IO.File.OpenWrite(filePath))
using (var uploadedFile = file.OpenReadStream())
{
var appWord = new Application();
if (appWord.Documents != null)
{
//yourDoc is your word document
var wordDocument = appWord.Documents.Open(file) ;
string pdfDocName = "pdfDocument.pdf";
if (wordDocument != null)
{
wordDocument.ExportAsFixedFormat(pdfDocName,
WdExportFormat.wdExportFormatPDF);
wordDocument.Close();
}
appWord.Quit();
}
uploadedFile.CopyTo(localFile);
}
}
ViewBag.Message = "Files are successfully uploaded";
// Get files from the server
var model = new FilesViewModel();
foreach (var item in Directory.GetFiles(Path.Combine(Directory.GetCurrentDirectory(), "upload")))
{
model.Files.Add(
new FileDetails { Name = System.IO.Path.GetFileName(item), Path = item });
}
return View(model);
}
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename is not availble");
var path = Path.Combine(Directory.GetCurrentDirectory(), "upload", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
private string GetContentType(string path)
{
var types = GetMimeTypes();
var ext = Path.GetExtension(path).ToLowerInvariant();
return types[ext];
}
private Dictionary<string, string> GetMimeTypes()
{
return new Dictionary<string, string>
{
{".txt", "text/plain"},
{".pdf", "application/pdf"},
{".doc", "application/vnd.ms-word"},
{".docx", "application/vnd.ms-word"},
{".xls", "application/vnd.ms-excel"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".csv", "text/csv"}
};
}```
//Get the path of existing Word document
string fullpath = #"...\..\DocToPDF.docx";
//Loads an existing Word document
WordDocument wordDocument = new WordDocument(fullpath, FormatType.Docx);
//Creates an instance of the DocToPDFConverter
DocToPDFConverter converter = new DocToPDFConverter();
//Converts Word document into PDF document
PdfDocument pdfDocument = converter.ConvertToPDF(wordDocument);
//Releases all resources used by DocToPDFConverter
converter.Dispose();
//Closes the instance of document objects
wordDocument.Close();
//Saves the PDF file
pdfDocument.Save("DocToPDF.pdf");
//Closes the instance of document objects
pdfDocument.Close(true);```
this is the NuGet documentation they had on the site, I have got problems at the 2nd row : on specifying the full path
Related
I'm creating zip archive using selected file pattern and need to have a fast method that can return it async when it is being built.
public async Task<FileStreamResult> DownloadStudy(long studyId, string Pattern= "*_70_0_70_0.dcm")
{
var FilePaths = System.IO.Directory.EnumerateFiles(studyDir, Pattern, SearchOption.AllDirectories);
var dir = new DirectoryInfo(studyDir);
var fName = dir.Name + ".zip";
var zipPath = Path.Combine(dir.Parent.FullName, fName);
var zipFileMemoryStream = new FileStream(zipPath,FileMode.Create);
using (ZipArchive archive = new ZipArchive(zipFileMemoryStream, ZipArchiveMode.Update, leaveOpen: true))
{
foreach (var filePath in FilePaths)
{
var filename = Path.GetFileName(filePath);
var pdir = Path.GetFileName(Path.GetDirectoryName(filePath));
archive.CreateEntryFromFile(filePath, pdir + "/" + filename);
}
}
zipFileMemoryStream.Seek(0, SeekOrigin.Begin);
return new FileStreamResult(zipFileMemoryStream, "application/octet-stream") { FileDownloadName = studyId.ToString() + ".zip" };
}
Is there a better way to have the download starts once the action is called and while the zip archive is being built?
I'm trying to upload data (image) from form to my .NET App. It saves the Path to the database correctly, but the images are not saved under "wwwroot/images". I will be grateful for your help.
public async Task<IActionResult> Create([Bind("Id,Brand,Model,Description,Price,ImageUrl,CategoryId")] Car car)
{
if (ModelState.IsValid)
{
string webRootPath = _hostEnvironment.WebRootPath;
var files = HttpContext.Request.Form.Files;
if (files.Count > 0)
{
string fileName = Guid.NewGuid().ToString();
var uploads = Path.Combine(webRootPath, "images");
var extenstion = Path.GetExtension(files[0].FileName);
var filePath = Path.Combine(uploads, fileName, extenstion);
car.ImageUrl = "images" + "\\" + fileName + extenstion;
using (var filesStreams = new FileStream(filePath, FileMode.Create))
{
files[0].CopyTo(filesStreams);
}
}
_context.Add(car);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["CategoryId"] = new SelectList(_context.Categories, "Id", "Name", car.CategoryId);
return View(car);
}
I would like to display a picture whose path it stores in the database
this is how it transfers the image file to the database.
public string UploadImage(IFormFile file)
{
if (file == null) throw new Exception("Pusty plik");
if (file.Length == 0)
{
throw new Exception("Pusty plik");
}
if (!ACCEPTED_FILE_TYPES.Any(s => s == Path.GetExtension(file.FileName).ToLower())) throw new Exception("Zły typ pliku");
if (string.IsNullOrWhiteSpace(host.WebRootPath))
{
host.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
var uploadFilesPath = Path.Combine(host.WebRootPath, "images");
if (!Directory.Exists(uploadFilesPath))
Directory.CreateDirectory(uploadFilesPath);
var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var filePath = Path.Combine(uploadFilesPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
file.CopyToAsync(stream);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), #"/wwwroot/images/", fileName);
return path;
}
here stores files:
https://zapodaj.net/a8829a7a3a90b.png.html
In your sample code I do not see path returning from database.
Also from security point of view it would be bad practice to return /wwwroot/images/ in response. You can create a folder on shared location and return shared location path.
Seems you question and same code isn't aligning.
Been strugling with a lot of problems. Using OpenXML on a ASP.NET Core server, I want to create a new docx document based on a template one. Once this document is fully saved, I want it to be sent to my client so he can download it directly. Here's my code :
public IActionResult Post([FromBody] Consultant consultant)
{
using (Stream templateStream = new MemoryStream(Properties.Resources.templateDossierTech))
using (WordprocessingDocument template =
WordprocessingDocument.Open(templateStream, false))
{
string fileName = environment.WebRootPath + #"\Resources\"+ consultant.FirstName + "_" + consultant.LastName + ".docx";
WordprocessingDocument dossierTechniqueDocument =
WordprocessingDocument.Create(fileName,
WordprocessingDocumentType.Document);
foreach (var part in template.Parts)
{
dossierTechniqueDocument.AddPart(part.OpenXmlPart, part.RelationshipId);
}
var body = dossierTechniqueDocument.MainDocumentPart.Document.Body;
var paras = body.Elements();
foreach (var para in paras)
{
foreach (var run in para.Elements())
{
foreach (var text in run.Elements())
{
if (text.InnerText.Contains("{{prenom}}"))
{
var t = new Text(text.InnerText.Replace("{{prenom}}", consultant.FirstName));
run.RemoveAllChildren<Text>();
run.AppendChild(t);
}
}
}
}
dossierTechniqueDocument.MainDocumentPart.Document.Save();
dossierTechniqueDocument.Close();
var cd = new System.Net.Mime.ContentDisposition
{
FileName = consultant.FirstName + "_" + consultant.LastName + ".docx",
Inline = true
};
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return File(System.IO.File.ReadAllBytes(fileName),"application/vnd.openxmlformats-officedocument.wordprocessingml.document","Dossier Technique");
}
}
As a first look, it looks like is saving well but when I try to open it on word, it says that it is corrupted for some reason.
That's the same problem when I try to send it. Once it's sent my client doesn't download it (Ajax query).
Do anyone of you have any idea how to fix it ?
Here is the function which creates a document from a template:
static void GenerateDocumentFromTemplate(string inputPath, string outputPath)
{
MemoryStream documentStream;
using (Stream stream = File.OpenRead(inputPath))
{
documentStream = new MemoryStream((int)stream.Length);
CopyStream(stream, documentStream);
documentStream.Position = 0L;
}
using (WordprocessingDocument template = WordprocessingDocument.Open(documentStream, true))
{
template.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
MainDocumentPart mainPart = template.MainDocumentPart;
mainPart.DocumentSettingsPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate",
new Uri(inputPath, UriKind.Absolute));
mainPart.Document.Save();
}
File.WriteAllBytes(outputPath, documentStream.ToArray());
}
In short: I would like to insert the content of a docx that contains images and bullets in another docx.
My problem: I used two approaches:
Manual merge
Altchunk
With both of them I got a corrupted word document as result.
If I remove the images from the docx that I would like to insert in another one, the result docx is OK.
My code:
Manual merge (thanks to https://stackoverflow.com/a/48870385/10075827):
private static void ManualMerge(string firstPath, string secondPath, string resultPath)
{
if (!System.IO.Path.GetFileName(firstPath).StartsWith("~$"))
{
File.Copy(firstPath, resultPath, true);
using (WordprocessingDocument result = WordprocessingDocument.Open(resultPath, true))
{
using (WordprocessingDocument secondDoc = WordprocessingDocument.Open(secondPath, false))
{
OpenXmlElement p = result.MainDocumentPart.Document.Body.Descendants<Paragraph>().Last();
foreach (var e in secondDoc.MainDocumentPart.Document.Body.Elements())
{
var clonedElement = e.CloneNode(true);
clonedElement.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().ToList().ForEach(blip =>
{
var newRelation = result.CopyImage(blip.Embed, secondDoc);
blip.Embed = newRelation;
});
clonedElement.Descendants<DocumentFormat.OpenXml.Vml.ImageData>().ToList().ForEach(imageData =>
{
var newRelation = result.CopyImage(imageData.RelationshipId, secondDoc);
imageData.RelationshipId = newRelation;
});
result.MainDocumentPart.Document.Body.Descendants<Paragraph>().Last();
if (clonedElement is Paragraph)
{
p.InsertAfterSelf(clonedElement);
p = clonedElement;
}
}
}
}
}
}
public static string CopyImage(this WordprocessingDocument newDoc, string relId, WordprocessingDocument org)
{
var p = org.MainDocumentPart.GetPartById(relId) as ImagePart;
var newPart = newDoc.MainDocumentPart.AddPart(p);
newPart.FeedData(p.GetStream());
return newDoc.MainDocumentPart.GetIdOfPart(newPart);
}
Altchunk merge (from http://www.karthikscorner.com/sharepoint/use-altchunk-document-assembly/):
private static void AltchunkMerge(string firstPath, string secondPath, string resultPath)
{
WordprocessingDocument mainDocument = null;
MainDocumentPart mainPart = null;
var ms = new MemoryStream();
#region Prepare - consuming application
byte[] bytes = File.ReadAllBytes(firstPath);
ms.Write(bytes, 0, bytes.Length);
mainDocument = WordprocessingDocument.Open(ms, true);
mainPart = mainDocument.MainDocumentPart;
#endregion
#region Document to be imported
FileStream fileStream = new FileStream(secondPath, FileMode.Open);
#endregion
#region Merge
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, "AltChunkId101");
chunk.FeedData(fileStream);
var altChunk = new AltChunk(new AltChunkProperties() { MatchSource = new MatchSource() { Val = new OnOffValue(true) } });
altChunk.Id = "AltChunkId101";
mainPart.Document.Body.InsertAfter(altChunk, mainPart.Document.Body.Elements<Paragraph>().Last());
mainPart.Document.Save();
#endregion
#region Mark dirty
var listOfFieldChar = mainPart.Document.Body.Descendants<FieldChar>();
foreach (FieldChar current in listOfFieldChar)
{
if (string.Compare(current.FieldCharType, "begin", true) == 0)
{
current.Dirty = new OnOffValue(true);
}
}
#endregion
#region Save Merged Document
mainPart.DocumentSettingsPart.Settings.PrependChild(new UpdateFieldsOnOpen() { Val = new OnOffValue(true) });
mainDocument.Close();
FileStream file = new FileStream(resultPath, FileMode.Create, FileAccess.Write);
ms.WriteTo(file);
file.Close();
ms.Close();
#endregion
}
I spent hours searching for a solution and the most common one I found was to use altchunk. So why is it not working in my case?
If you are able to use the Microsoft.Office.Interop.Word namespace, and able to put a bookmark in the file you want to merge into, you can take this approach:
using Microsoft.Office.Interop.Word;
...
// merge by putting second file into bookmark in first file
private static void NewMerge(string firstPath, string secondPath, string resultPath, string firstBookmark)
{
var app = new Application();
var firstDoc = app.Documents.Open(firstPath);
var bookmarkRange = firstDoc.Bookmarks[firstBookmark];
// Collapse the range to the end, as to not overwrite it. Unsure if you need this
bookmarkRange.Collapse(WdCollapseDirection.wdCollapseEnd);
// Insert into the selected range
// use if relative path
bookmarkRange.InsertFile(Environment.CurrentDirectory + secondPath);
// use if absolute path
//bookmarkRange.InsertFile(secondPath);
}
Related:
C#: Insert and indent bullet points at bookmark in word document using Office Interop libraries