Alternative Save/OpenBinaryDirect methods for CSOM for SharePoint Online - asp.net-core-webapi

Based on the doc from MS https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/using-csom-for-dotnet-standard, Save/OpenBinaryDirect methods is not available for .NET core app, they suggest to use regular file API, so what is the alternative way to read/write files stored in SharePoint online? what is the regular file API? does anyone done this? any example code/documentation?

Download file in .NET Core CSOM:
using (var authenticationManager = new AuthenticationManager())
using (var context = authenticationManager.GetContext(site, user, password))
{
context.Load(context.Web, p => p.Title);
context.ExecuteQuery();
Microsoft.SharePoint.Client.File file = context.Web.GetFileByUrl("https://tenant.sharepoint.com/sites/michael/Shared%20Documents/aa.txt");
context.Load(file);
context.ExecuteQuery();
string filepath = #"C:\temp\" + file.Name;
Microsoft.SharePoint.Client.ClientResult<Stream> mstream = file.OpenBinaryStream();
context.ExecuteQuery();
using (var fileStream = new System.IO.FileStream(filepath, System.IO.FileMode.Create))
{
mstream.Value.CopyTo(fileStream);
}
using (System.IO.StreamReader sr = new System.IO.StreamReader(mstream.Value))
{
String line = sr.ReadToEnd();
Console.WriteLine(line);
}
}
Upload file in .NET Core CSOM:
string filepath = #"C:\temp\aa.txt";
FileCreationInformation newfile = new FileCreationInformation();
newfile.Url = System.IO.Path.GetFileName(filepath);
newfile.Content= System.IO.File.ReadAllBytes(filepath);
List library = context.Web.Lists.GetByTitle("Documents");
Microsoft.SharePoint.Client.File uploadFile = library.RootFolder.Files.Add(newfile);
context.Load(uploadFile);
context.ExecuteQuery();

Jerry's answer got me there, but I wanted to add a couple of extras that weren't mentioned in his answer.
If your file destination isn't the main Documents list, instead of the Lists.GetByTitle call use
var folder = context.Web.GetFolderByServerRelativeUrl(...);
File uploadFile = folder.Files.Add(newfile);
If you're updating a file, you've got to set
newFile.Overwrite = true;
And if the file you're uploading/replacing is greater than 2MB, you've got to use the ContentStream instead of Content
FileCreationInformation newfile = new FileCreationInformation
{
Url = relativeUrl,
ContentStream = stream,
Overwrite = true
};

Related

System.Net.WebClient.DownloadStringTaskAsync method when webpage contains ™ or other special characters

I am using the System.Net.WebClient.DownloadStringTaskAsync async method to upload a web page content and process it or just save it on my local folder. Everything is fine but when the web page contains some special characters like ™ or ®, they are not getting downloaded. Am I missing something here?
String contentToScrapeURL = "https://www.naylornetwork.com/aaho-advertorial/newsletter.asp?issueID=89542";
Boolean success = true;
using (System.Net.WebClient wc = new System.Net.WebClient())
{
String pageSourceCode = await wc.DownloadStringTaskAsync(contentToScrapeURL);
String path = #"C:\MyProjects\TestingThings\App_Data\" + "test.html";
File.WriteAllText(path, pageSourceCode);
}
Found it, or remembered it.
I did set the System.Net.WebClient.Encoding to Encoding.UTF8
So this below is the updated code
using (System.Net.WebClient wc = new System.Net.WebClient())
{
wc.Encoding = Encoding.UTF8;
String pageSourceCode = await wc.DownloadStringTaskAsync(contentToScrapeURL);
String path = #"C:\MyProjects\TestingThings\App_Data\" + "test.html";
File.WriteAllText(path, pageSourceCode);
}

Spire.xls - return a File from a stream for client download

Here is what I'm trying to accomplish.
I am creating an asp.net MVC application. My restrictions are that I cannot programmatically save anything to the file structure of the server, so I can't save it as a physical file on the host, and then grab it for client download.
I am loading a PDF to a stream, extracting information from the PDF, dynamically building an excel file, and then offering the file for download to the client. My code is below.
// Loads the incoming PDF document to stream
PdfDocument doc = new PdfDocument();
using (var stream = model.BudgetPdfFile.OpenReadStream())
{
doc.LoadFromStream(stream);
}
var pageCount = doc.Pages.Count;
var date = DateTime.Now.ToShortDateString().Replace("/", "-");
// Extracts data from the PDF and separates it by NewLine
SimpleTextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
StringBuilder allText = new StringBuilder();
for (var i = 0; i < pageCount; i++)
{
allText.Append(doc.Pages[i].ExtractText(strategy));
}
var fullDocText = allText.ToString();
List<string> linesList = new List<string>(fullDocText.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList());
// generates a comparison list for output data manipulation from static data
var finalList = linesList.BuildFinalList(budgetItems);
// creates a new Spire.PDF.Workbook for the final output excel file
var result = new Workbook();
// checks for whether the submitted budget is for a case in litigation or not and builds the correct excel workbook
if (model.isTrial)
{
result = ExportExcelBudget.TrialBudgetSheet(model, finalList);
}
else
{
result = ExportExcelBudget.PreTrialBudgetSheet(model, finalList);
}
Absolutely everything up to the last section below works perfectly. However, I cannot figure out how to load the workbook into a new stream and then return the file for download.
// saves the final workbook to a stream and offers it for download to the client
Stream outStream = new MemoryStream();
var fileName = "Budget Report_" + model.ClaimNumber + "_" + date + ".xlsx";
var contentType = "application/vnd.ms-excel";
result.SaveToStream(outStream, Spire.Xls.FileFormat.Version2016);
return File(outStream, contentType, fileName);
I've searched and tried multiple different variations but when the application hits the return File(), it returns a null.
I've stepped through execution and the results seem to be there, but it's not passing anything. Any help on what is wrong here would be greatly appreciated.
Stream outStream = new MemoryStream();
var fileName = "Budget Report_" + model.ClaimNumber + "_" + date + ".xlsx";
var contentType = "application/vnd.ms-excel";
result.SaveToStream(outStream, Spire.Xls.FileFormat.Version2016);
**outStream.Position = 0;**
return File(outStream, contentType, fileName);
Had to reset the stream position to 0. Working perfectly now.

Xamarin Forms: Get the path of an image file stored on the shared project?

I am trying to upload an image file as ByteArrayContent through my web service. I have added all the images to the shared project and set the build action as Embedded resource.
Following is my code:
var fileBytes = File.ReadAllBytes("Avatars." + selectedAvatar);
var byteContent = new ByteArrayContent(fileBytes);
content.Add(byteContent, "file", selectedAvatar);
When I try like above I am getting System.IO.FileNotFoundException: Could not find file "/Projectname.Avatars.ic_avatar01_xx.png"
Added the images directly inside a folder in the shared project like the below screenshot.
:
I tried changing the . with a / in the file path, like below:
var fileBytes = File.ReadAllBytes("Avatars/" + selectedAvatar);
var byteContent = new ByteArrayContent(fileBytes);
content.Add(byteContent, "file", selectedAvatar);
But in that case, I am getting the System.IO.DirectoryNotFoundException: Could not find a part of the path "/Avatars/ic_avatar01_xx.png"
What is the correct way to get the path of an image file stored on a shared project?
Also tried another approach:
string avatarFileName = "Avatars/" + selectedAvatar;
var assembly = typeof(ProfilePage).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{avatarFileName}");
content.Add(stream, "file", avatarFileName);
But in the above case I am getting the below error:
If you want to upload the image with Stream , you could check the following code
private async Task<string> UploadImage(Stream FileStream)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://your.url.com/");
MultipartFormDataContent form = new MultipartFormDataContent();
HttpContent content = new StringContent("fileToUpload");
form.Add(content, "fileToUpload");
content = new StreamContent(FileStream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "fileToUpload",
FileName = "xxx.png"
};
form.Add(content);
var response = await client.PostAsync("http://your.url.com/", form);
return response.Content.ReadAsStringAsync().Result;
}
Option 2:
You could also use the plugin FileUploaderPlugin . It support uploading multiple files at once
Uploading from a file path
CrossFileUploader.Current.UploadFileAsync("<URL HERE>", new FilePathItem("<REQUEST FIELD NAME HERE>","<FILE PATH HERE>"), new Dictionary<string, string>()
{
{"<HEADER KEY HERE>" , "<HEADER VALUE HERE>"}
}
);
Option 3:
The first parameter of MultipartFormDataContent is HttpContent. To handle the stream, try using the StreamContent type which inherits from the HttpContent. Get the streamContent from the stream and add id to the MultipartFormDataContent.
string avatarFileName = "Avatars." + selectedAvatar;
var assembly = typeof(ProfilePage).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{avatarFileName}");
var streamContent = new StreamContent(stream);
content.Add(streamContent, "file", avatarFileName);

Save a document in Alfresco shared folder via Rest API

I'm try to upload a file to the shared folder...
This is my code.
// using httpclient-4.5
Path filePath = Paths.get("C:/afile.txt");
String ticket = getTicket(); // get a ticket via /alfresco/service/api/login...
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("http://localhost:8080/alfresco/service/api/upload?alf_ticket=" + ticket);
MultipartEntityBuilder entity = MultipartEntityBuilder.create();
StringBody descriptionBody = new StringBody("a test", ContentType.TEXT_PLAIN);
StringBody siteId = new StringBody("company_home", ContentType.TEXT_PLAIN); // how can upload the file
StringBody containerid = new StringBody("/Shared", ContentType.TEXT_PLAIN); // in the shared folder??
entity.addBinaryBody("filedata", filePath.toFile());
entity.addPart("siteid", siteId);
entity.addPart("containerid", containerid);
post.setEntity(entity.build());
CloseableHttpResponse postResponse = client.execute(post);
// ...
Can anyone help me? Thanks.

Tridion core service How to download binary file of a multimedia component

I have a requirement where I need to download binary file of a multimedia component but when I access the properties exposed of BinaryContentData class then there is no property to download an image file. Although for uploading file, Core Service have a property namely UploadFromFile.
So is there a way to download binary file to a temp location. Below is the code I am using:
core_service.ServiceReference1.SessionAwareCoreService2010Client client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword"; client.Open();
ComponentData component = (ComponentData)client.TryCheckOut(
multimediaComponentURI, new ReadOptions());
BinaryContentData binaryData = component.BinaryContent;
Please Suggest.
There is a helper function called streamDownloadClient.DownloadBinaryContent inside Tridion.ContentManager.CoreService.Client.dll that you can use.
I have created the following function that I usually reuse for that purpose:
private static void CreateBinaryFromMultimediaComponent(string tcm)
{
Tridion.ContentManager.CoreService.Client.StreamDownloadClient streamDownloadClient = new StreamDownloadClient();
SessionAwareCoreServiceClient client = new SessionAwareCoreServiceClient("netTcp_2011");
ComponentData multimediaComponent = client.Read(tcm, new ReadOptions()) as ComponentData;
// Generate you own file name, and file location
string file = "D:\\MyTempLocation\\" + Path.GetFilename(multimediaComponent.BinaryContent.Filename);;
// Write out the existing file from Tridion
FileStream fs = File.Create(file);
byte[] binaryContent = null;
if (multimediaComponent.BinaryContent.FileSize != -1)
{
Stream tempStream = streamDownloadClient.DownloadBinaryContent(tcm);
var memoryStream = new MemoryStream();
tempStream.CopyTo(memoryStream);
binaryContent = memoryStream.ToArray();
}
fs.Write(binaryContent, 0, binaryContent.Length);
fs.Close();
}

Resources