Uploading document body to SharePoint from CRM Notes C# - c#

I am able to upload the document but when I'm viewing/downloading it, there seems to be an error. It says it ran into a problem opening this PDF.
Ran into a problem
I have the following code
using (var stream = new System.IO.MemoryStream())
{
byte[] myByte = System.Text.ASCIIEncoding.Default.GetBytes(documentBody);
foreach (byte element in myByte)
{
stream.WriteByte(element);
}
stream.Seek(0, SeekOrigin.Begin);
var newFile = new FileCreationInformation { Url = fileName, ContentStream = stream, Overwrite = true };
file = list.RootFolder.Files.Add(newFile);
file.CheckOut();
file.CheckIn(string.Empty, CheckinType.MajorCheckIn);
context.Load(file);
context.ExecuteQuery();
}
The documentBody is the field documentbody from Annotation (note). Is there something wrong with the stream?

The documentBody is Base64 encoded in CRM, so you many need to decode it first before saving into SharePoint.
Try this to get the document data.
byte[] data = Convert.FromBase64String(e.Attributes["documentbody"].ToString());

Related

How to retrieve a pdf from MongoDB database using c#

I have a collection of pdf files saved to MongoDB. I'm attempting to convert all the files to base64 but I'm having trouble retrieving the actual files from the database. The file path is not what I'm expecting and I'm unsure of what else to try
Below is the code I have tried. The error message is:
"System.IO.IOException Message=The filename, directory name, or volume label syntax is incorrect. : 'C:\Users\Jabari.LAPTOP-FERO3UB5\Desktop\codebase\LMO\API\LMO.Api\https:\LMOdevstorage.blob.core.windows.net\documents\57a36b7e6789102ddf\J_Broomstick58059342787ba42f12345.pdf'
From what I can see it's trying to pull from my local codebase and not the actual database. I'm not sure why this is. I'm new to MongoDB operations.
Below is my code
var file = document.AzureDocumentUri;
if (file != null)
{
Byte[] bytes = File.ReadAllBytes(file);
String base64String = Convert.ToBase64String(bytes);
StreamWriter sw64 = new StreamWriter($"{filePath}test64.txt");
sw64.Write(base64String);
sw64.Close();
sw64.Dispose();
}
What I'm expecting to happen is to be able to access the pdf file directly from the database and read it into memory then convert it to base64.
Why is it attempting to download from my local directory instead the collection from the database?
Byte[] bytes = File.ReadAllBytes(file);
is strange, you can't download URI like this.
To find the best way to use file in MongoDB look at GridFS.
MemoryStream ms = new MemoryStream(new byte[] { 0x00, 0x01, 0x02 });
ms.Position = 0;
// MemoryStream ms2 = new MemoryStream(await File.ReadAllBytesAsync("test.pdf"));
// Write to MongoDB
// There is a limitation of 16 MB in record size for mongodb, this what GridFS handle, unlimited file size.
// https://www.mongodb.com/docs/manual/core/document/#:~:text=Document%20Size%20Limit,MongoDB%20provides%20the%20GridFS%20API.
GridFSBucket gridFSBucket = new GridFSBucket(db);
ObjectId id = await gridFSBucket.UploadFromStreamAsync("exemple.bin", ms);
// Get the file
MemoryStream ms3 = new MemoryStream();
await gridFSBucket.DownloadToStreamAsync(id, ms3);
Full example here
https://github.com/iso8859/learn-mongodb-by-example/blob/main/dotnet/02%20-%20Intermediate/StoreFile.cs

Convert docx stream to pdf directly

I need to convert any file coming from web response into .pdf format, I'm currently getting it word docx file format from the URL and saving it into memory stream so i can later insert it in it's designated library.
The problem I'm facing now is that I'm saving my docx files directly into .pdf by putting an extension at the end which obviously ends up not opening the file later, So i'm trying to convert my memory stream into pdf directly .
Here is my piece of code that i tried to convert the the stream to .pdf but it looks like the file isn't getting converted correctly.
private Stream DownloadFromUrl(string url)
{
var webRequest = WebRequest.Create(url);
webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
webRequest.PreAuthenticate = true;
webRequest.UseDefaultCredentials = true;
//EventLogUtility.LogInformationMessage(DocumentURL);
string message = string.Empty;
using (Stream outputStream = new MemoryStream())
{
using (var response = webRequest.GetResponse())
{
using (var content = response.GetResponseStream())
{
var memory = new MemoryStream();
content.CopyTo(memory);
Document doc = new Document(memory);
doc.Save(memory, SaveFormat.Pdf);
return memory;
}
}
}
}
If the content in the stream is actually in the Microsoft Word file format (and not just plain text), then you need to map the format to the file format for PDF. I know there is a 'Print to PDF' function available in Word, you could try looking into that.

Can save stream as local file, but when returning it as HttpResponseMessage - always empty file

I want to write export/download functionality for files from external API.
I've created separate Action for it. Using external API I can get stream for that file.
When I am saving that stream to local file, everything is fine, file isn't empty.
var exportedFile = await this.GetExportedFile(client, this.ReportId, this.WorkspaceId, export);
// Now you have the exported file stream ready to be used according to your specific needs
// For example, saving the file can be done as follows:
string pathOnDisk = #"D:\Temp\" + export.ReportName + exportedFile.FileSuffix;
using (var fileStream = File.Create(pathOnDisk))
{
await exportedFile.FileStream.CopyToAsync(fileStream);
}
But when I return exportedFile object that contains in it stream and do next:
var result = await this._service.ExportReport(reportName, format, CancellationToken.None);
var fileResult = new HttpResponseMessage(HttpStatusCode.OK);
using (var ms = new MemoryStream())
{
await result.FileStream.CopyToAsync(ms);
ms.Position = 0;
fileResult.Content = new ByteArrayContent(ms.GetBuffer());
}
fileResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"{reportName}{result.FileSuffix}"
};
fileResult.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return fileResult;
Exported file is always empty.
Is it problem with stream or with code that try to return that stream as file?
Tried as #Nobody suggest to use ToArray
fileResult.Content = new ByteArrayContent(ms.ToArray());
the same result.
Also tried to use StreamContent
fileResult.Content = new StreamContent(result.FileStream);
still empty file.
But when I'm using StreamContent and MemmoryStream
using (var ms = new MemoryStream())
{
await result.FileStream.CopyToAsync(ms);
ms.Position = 0;
fileResult.Content = new StreamContent(ms);
}
in result I got
{
"error": "no response from server"
}
Note: from 3rd party API I get stream that is readonly.
you used GetBuffer() to retrieve the data of the memory stream.
The function you should use is ToArray()
Please read the Remarks of the documentation of these functions.
https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream.getbuffer?view=net-6.0
using (var ms = new MemoryStream())
{
ms.Position = 0;
await result.FileStream.CopyToAsync(ms);
fileResult.Content = new ByteArrayContent(ms.ToArray()); //ToArray() and not GetBuffer()
}
Your "mistake" although it's an obvious one is that you return a status message, but not the actual file itself (which is in it's own also a 200).
You return this:
var fileResult = new HttpResponseMessage(HttpStatusCode.OK);
So you're not sending a file, but a response message. What I'm missing in your code samples is the procedure call itself, but since you use a HttpResonseMessage I will assume it's rather like a normal Controller action. If that is the case you could respond in a different manner:
return new FileContentResult(byteArray, mimeType){ FileDownloadName = filename };
where byteArray is ofcourse just a byte[], the mimetype could be application/octet-stream (but I suggest you'd actually find the correct mimetype for the browser to act accordingly) and the filename is the filename you want the file to be named.
So, if you were to stitch above and my comment together you'd get this:
var exportedFile = await this.GetExportedFile(client, this.ReportId, this.WorkspaceId, export);
// Now you have the exported file stream ready to be used according to your specific needs
// For example, saving the file can be done as follows:
string pathOnDisk = #"D:\Temp\" + export.ReportName + exportedFile.FileSuffix;
using (var fileStream = File.Create(pathOnDisk))
{
await exportedFile.FileStream.CopyToAsync(fileStream);
}
return new FileContentResult(System.IO.File.ReadAllBytes(pathOnDisk), "application/octet-stream") { FileDownloadName = export.ReportName + exportedFile.FileSuffix };
I suggest to try it, since you still report a 200 (and not a fileresult)

Modifed word document not saving in memorystream

I am getting a word document from SharePoint using Microsoft graph API as a stream and changing some content in that file and downloading the saved content as a file but when I open the file, the modified content is not available. The downloaded file still shows the original content.
using (var memoryStream = new MemoryStream())
{
templateStream.Position = 0;
// Copying the stream that I've got into memory stream
await templateStream.CopyToAsync(memoryStream).ConfigureAwait(false);
memoryStream.Position = 0;
using (var wordDocument = WordprocessingDocument.Open(memoryStream, true))
{
RevisionAccepter.AcceptRevisions(wordDocument);
var document = wordDocument.MainDocumentPart.GetXDocument();
var content = document.Descendants(W.p).ToList();
//based on the dictionary I've I am replacing the contents of the file
foreach (var field in dataDictionary)
{
var regex = new Regex(field.Key, RegexOptions.IgnoreCase);
OpenXmlRegex.Replace(content, regex, field.Value.ToString(), null);
}
//not showing the modified content
wordDocument.Save();
//this is also not updating the memorystream variable with the modified content
wordDocument.MainDocumentPart.Document.Save();
memoryStream.Position = 0;
await memoryStream.FlushAsync().ConfigureAwait(false);
}
var result = memoryStream.ToArray();
memoryStream.Flush();
return result;
}
once I got the byte array from the above code I am downloading the file using this line from my controller
return File(returnResponse, System.Net.Mime.MediaTypeNames.Application.Octet, $"Test-
{System.DateTime.Now}.docx");
What am I doing wrong?
As outlined in this answer you need to call PutXDocument() method on the MainDocumentPart for your changes to be successfully reflected, because currently, you are making changes but not commiting them to the required document.

How to save the docx binary data to file in web api C#

I'm fetching a byte[] of a docx file from one API to another and processing it like Application.Documents.Open(array); or File.WriteAllBytes(path, array);
I think the data received is in some UTF-8 format but i have no idea how to convert and process them
Fetching the file from the API using below code.
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
The output(byte[]) is received as string like this.
string result = "PK[][]?......";
Please check the postman screenshot
And trying with below code to save to folder but not working
byte[] res = result .ToArray();
File.WriteAllBytes(#"C:\temp\myfile.docx", res);
also tried this but didn't work,
byte[] mybytearray = Convert.FromBase64String(t);
byte[] barr = Encoding.ASCII.GetBytes(hardcode);
Maybe you should use BinaryReader instead of StreamReader.
See also: https://stackoverflow.com/a/8613300/1438829

Categories