OpenXML - how to download WordprocessingDocument after replacing some text - asp.net-core-mvc

I have followed the example from https://learn.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part to open a DOTX template & replace some text. However after I StreamWrite the updated docText successfully & place it into a stream for download, the resulting DOCX file issues "Excel found unreadable content" when opened.
public async Task<MemoryStream> DownloadDoc(string pin)
{
using (var doc = WordprocessingDocument.CreateFromTemplate(DOTX_PATH, false))
{
var docText = string.Empty;
using (var sr = new StreamReader(doc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("replace this");
docText = regexText.Replace(docText, "with this");
using (var sw = new StreamWriter(doc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
// uncommented, this SaveAs line works and DOCX opens without error & looks good
//doc.SaveAs("C:\\Temp\\test.docx");
doc.Save();
// But I want to download it without saving it to disk. Here's the piece I'm missing
// - how to get a VALID stream returned for download? The DOCX is downloaded,
// but "Excel found unreadable content" error is issued when opened.
var ms = new MemoryStream();
doc.MainDocumentPart.GetStream().CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
return null;
}

Related

Rename a recorded file every time I save a record in xamarin

I am saving my records using this code:
string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
public string fileName { get; set; }
fileName = Path.Combine(path, "sample.wav");
if (!recorder.IsRecording)
{
recorder.StopRecordingOnSilence = TimeoutSwitch.IsToggled;
//Start recording
var audioRecordTask = await recorder.StartRecording();
BtnDoneRec.IsEnabled = false;
await audioRecordTask;
RecEditor.IsEnabled = true;
BtnDoneRec.IsEnabled = false;
PlayButton.IsEnabled = true;
var filePath = recorder.GetAudioFilePath();
if (filePath != null)
{
var stream = recorder.GetAudioFileStream();
using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fileStream);
}
}
}
else
{
//stop recording ...
await recorder.StopRecording();
}
I want my record to have a specific name which is labeled with my RecEditor
using (var streamReader = new StreamReader(fileName))
{
File.Move("sample.wav", RecEditor.Text + ".wav");
}
So it will rename "sample.wav" to "RecEditor text.wav" every time I click my save button.
But when I click save, it gives me this record
System.IO.FileNotFoundException: 'Could not find file '/sample.wav'.'
The record is stored in /storage/emulated/0/sample.wav
The sample.wav is created in my device but I don't know why it give me 'Could not find file '/sample.wav'.' error. What am i doing wrong here?
I believe that what you're looking is something like this:
if(File.Exists(fileName))
{
var newFileName = Path.Combine(path, $"{RecEditor.Text}.wav");
File.Move(fileName, newFileName);
}
You don't need to open a new Stream as you are doing. Also, you need to put the full file path not only the file name.
You might want to validate that RecEditor.Text is not empty before using its value for the newfileName
Hope this helps.-

Android post image to Facebook comment

This is a followup to my previous question: Xamarin.Forms App return data to calling App
That works perfectly and I can share images to anywhere, except to Facebook comments. When I click the camera on the content box the app can be selected, I can select the image, Set result and Finish are called, and the app closes and it sends data to Facebook, and then however I then get the error : The image could not be uploaded, try again?
I can't find any fundamental differences between posting to a status or a comment, so I'm guessing it's subtle. Any thoughts on how I can change my intent to post properly?
Adding for completeness:
Bitmap b = null;
string url;
if (!string.IsNullOrEmpty(this.saleItems[i].ImageUrl))
{
url = this.saleItems[i].ImageUrl;
}
else
{
url = await FileHelper.GetLocalFilePathAsync(this.saleItems[i].Id);
}
//download
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
b = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
//set local path
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose();
var imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent();
sharingIntent.SetAction(Intent.ActionSend);
sharingIntent.SetType("image/*");
sharingIntent.PutExtra(Intent.ExtraText, "some txt content");
sharingIntent.PutExtra(Intent.ExtraStream, imageUri);
sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
//await SaleItemDataService.Instance.BuySaleItemAsync(this.saleItem);
SetResult(Result.Ok, sharingIntent);
Finish();
Use below:
Intent sharingIntent = new Intent();
string imageUri = "file://" + requestedUri;
sharingIntent.SetData(Android.Net.Uri.Parse(imageUri));

How to download files from Wikimedia Commons by API?

How can I download a lot of audio (.ogg) files from Wikimedia Commons? Is it possible using the Mediawiki API?
You can use MediaWiki API to get the url download links not only for .ogg but also to any other image or media file uploaded on Wikimedia Commons. From the response you can easy download each one file. Here is an example in C#:
private static void GetFiles(List<string> fileNames)
{
//Get HTML request with all file names
var url = "https://commons.wikimedia.org/w/api.php?action=query&format=xml" +
"&prop=imageinfo&iiprop=url&titles=File:" + string.Join("|File:", fileNames);
using (var webResponse = (HttpWebResponse)WebRequest.Create(url).GetResponse())
{
using (var reader = new StreamReader(webResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
//Get all file url links by parsing the XML response
var links = XElement.Parse(response).Descendants("ii")
.Select(x => x.Attribute("url").Value);
foreach (var link in links)
{
//Save the current file on the disk
using (var client = new WebClient())
{
var fileName = link.Substring(link.LastIndexOf("/") + 1);
client.DownloadFile(link, fileName);
}
}
}
}
}
Usage:
//list of files to download
var fileNames = new List<string>() {
"Flag of France.svg", "Black scorpion.jpg", "Stop.png", //image
"Jingle Bells.ogg", "Bach Astier 15.flac", //audio
"Cable Car.webm", "Lion.ogv", //video
"Animalibrí.gif", //animation
};
GetFiles(fileNames);
Note: The API has limit for the files:
Maximum number of values is 50 (500 for bots).
So, if you need to download more files, you will have to split the list in parts and to create another requests.

Writing CSV to MemoryStream using LinqToCSV does not return any data

I've verified using System.Text.Encoding.ASCII.GetString(ms.ToArray)); that my memorystream has the expected data.
However using the LinqToCSV nuget library will not generate my csv file. I get no errors or exceptions thrown. I just get an empty file when I'm prompted to open the file.
Here is my Action Method
public FileStreamResult Export(){
var results = _service.GetProperties().Take(3);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.TextWriter txt = new System.IO.StreamWriter(ms);
CsvFileDescription inputFileDescription = new CsvFileDescription{
SeparatorChar =',',
FirstLineHasColumnNames = true
}
;
CsvContext csv = new CsvContext();
csv.Write(results,txt,inputFileDescription);
return File(ms , "application/x-excel");
}
I find it interesting, if I change the return type to contentResult, and the return method to Content() and pass it System.Text.Encoding.ASCII.GetString(ms.ToArray)); I do get a browser window showing my data.
Make sure you reset stream position to 0. Also make sure you flush your StreamWriter before that.
Calling the Web API method to return CVS file from JavaScript.
public HttpResponseMessage Bidreport([FromBody]int formData).....
Fill in your IEnumerable<YourObject>query = from LINQ query
....
This is how to return it:
using (var ms = new MemoryStream())
{
using (TextWriter txt = new StreamWriter(ms))
{
var cc = new CsvContext();
cc.Write(query, txt, outputFileDescription);
txt.Flush();
ms.Position = 0;
var fileData = Encoding.ASCII.GetString(ms.ToArray());
var result = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(fileData)};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-excel");
return result;
}
}

.net mvc3 iTextSharp how to add image to pdf in memory stream and return to browser

I have a .pdf file stored in my database, and I have a signature file (.png) stored in my database. I am trying to use iTextSharp to add the signature image to the .pdf file, and display the result to the browser.
Here is my code:
byte[] file = Repo.GetDocumentBytes(applicantApplication.ApplicationID, documentID);
byte[] signatureBytes = Repo.GetSignatureBytes((Guid)applicantApplicationID, signatureID);
iTextSharp.text.Image signatureImage = iTextSharp.text.Image.GetInstance(signatureBytes);
iTextSharp.text.Document document = new iTextSharp.text.Document();
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(file, 0, file.Length, true, true))
{
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
signatureImage.SetAbsolutePosition(200, 200);
signatureImage.ScaleAbsolute(200, 50);
document.Add(signatureImage);
document.Close();
return File(ms.GetBuffer(), "application/pdf");
}
The page loads, and there is a .pdf with a signature, but the original document is nowhere to be found. It looks like I'm creating a new .pdf file and putting the image in there instead of editing the old .pdf file.
I have verified that the original .pdf document is being loaded into the "file" variable. I have also verified that the length of the MemoryStream "ms" is the same as the length of the byte[] "file".
I ended up doing something like this in my repository:
using (Stream inputPdfStream = new MemoryStream(file, 0, file.Length, true, true))
using (Stream inputImageStream = new MemoryStream(signatureBytes, 0, signatureBytes.Length, true, true))
using (MemoryStream outputPdfStream = new MemoryStream())
{
var reader = new PdfReader(inputPdfStream);
var stamper = new PdfStamper(reader, outputPdfStream);
var cb = stamper.GetOverContent(1);
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(inputImageStream);
image.SetAbsolutePosition(400, 100);
image.ScaleAbsolute(200, 50);
cb.AddImage(image);
stamper.Close();
return outputPdfStream.GetBuffer();
}
I adapted it from a few other answers on StackOverflow

Resources