I have a web service that currently passes base64 image format, However, How can I insert it into a sharepoint library? should i convert it to bytes array ?
Yes, need to read image file stream and then use Microsoft.SharePoint.Client.File.SaveBinaryDirect to save into SharePoint library:
var fileName=#"C:\Test.jpg";
using (ClientContext context = new ClientContext("http://sp/"))
{
using (var fs = new FileStream(fileName, FileMode.Open))
{
var fi = new FileInfo(fileName);
var list = context.Web.Lists.GetByTitle("Documents");
context.Load(list.RootFolder);
context.ExecuteQuery();
var fileUrl = String.Format("{0}/{1}", list.RootFolder.ServerRelativeUrl, fi.Name);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, fileUrl, fs, true);
}
}
Here is a similiar thread for your reference:
How to Upload Images to SharePoint Online(Office 365) Picture-library using CSOM (Java Script)?
Related
I have an Azure application built with ASP.NET Core using the MVC pattern. Document uploads are stored in Azure Blob Containers and the C# upload code I wrote is working great.
I am using Azure.Storage.Blobs version 12.14.1
Here is my download blob code:
//get document metadata stored in sql table, id comes from a method param
var document = _unitOfWork.Documents.GetById(id);
if (document == null)
{
throw new FileNotFoundException();
}
//get connection and container from appsettings.json
string connection = _appConfig.AzureStorageConnection;
string containerName = _appConfig.AzureStorageContainer;
//work with blob client
var serviceClient = new BlobServiceClient(connection);
var container = serviceClient.GetBlobContainerClient(containerName);
var fileName = document.UniqueDocumentName;
var blobClient = container.GetBlobClient(document.UniqueDocumentName);
using (FileStream fileStream = System.IO.File.OpenWrite("<path>"))
{
blobClient.DownloadTo(fileStream);
}
After I get to using code to set up the file stream, I don't understand what to pass into the OpenWrite method as a path. This application is a B2C app and so how do I just prompt a user to download the file?
I do get a file download with the above code but the file is called download.xml. That is not the file that should be downloaded. I expected the download file to be an .odt file.
Documentation seems to be very sparse on downloading from Azure Blob Storage
EDIT 1.
I got rid of the FileStream and did this instead:
MemoryStream ms = new MemoryStream();
ms.Position = 0;
blobClient.DownloadTo(ms);
return new FileStreamResult(ms, document.FileType);
I did this instead of using FileStream and returned FileResult instead:
MemoryStream ms = new MemoryStream();
ms.Position = 0;
blobClient.DownloadTo(ms);
return new FileStreamResult(ms, document.FileType);
I'm writing a telegram bot that takes jpg from it's users and sends it back as stickers.
I did this correctly by downloading jpg, change the extension of file to png and upload and send it back as a sticker message to the user. as shown below:
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var filename = file.FileId + "." + file.FilePath.Split('.').Last();
var pngFileName = filename.Split('.')[0] + ".png";
using (var saveImageStream = System.IO.File.Open(pngFileName, FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
using (var stream = System.IO.File.Open(pngFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
but the these stickers don't load in telegram on IOS devices and this code just works for telegram users on android. I tried to just changing the extension of jpg file to webp but it didn't work.
after that I downloaded the standard telegram stickers and found that the standard format of stickers in telegram is webp files.
now I want to know how can I convert received jpg file to webp file.
I searched alot and just find this , found here .
using (Image image = Image.FromFile("image.jpg"))
{
Bitmap bitmap = new Bitmap(image);
WebPFormat.SaveToFile("image.webp", bitmap);
}
I added it's files to my project and I added "using LibwebpSharp;" at the top of my code, but when I add it's sample code, the VS cannot find "WebpFormat" class.
please help me and answer my question:
"How can I convert jpg to webp in C# telegram bot?"
thank you
I solved this problem in this way:
I installed Imazen.WebP nuget.
I downloaded the 32bit dll from here and added it to release folder.
I added "using Imazen.WebP;in top of my code
I used this code to convert jpg to webp.
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var jpgFileName = file.FileId + ".jpg";
using (var saveImageStream = System.IO.File.Open(jpgFileName,FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
var webpFileName = file.FileId + ".webp";
using (Bitmap bitmap = new Bitmap(jpgFileName))
{
using (var saveImageStream = System.IO.File.Open(webpFileName, FileMode.Create))
{
var encoder = new SimpleEncoder();
encoder.Encode(bitmap, saveImageStream, 20);
}
}
using (var stream = System.IO.File.Open(webpFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
System.IO.File.Delete(jpgFileName);
System.IO.File.Delete(webpFileName);
Install the following packages first using Visual Studio's NuGet package manager:
Install-Package System.Drawing.Common
Install-Package ImageProcessor
Install-Package ImageProcessor.Plugins.WebP
Then use this code for conversion:
using (var webPFileStream = new FileStream(WebpFilePath, FileMode.Create))
{
using (ImageFactory imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(File.OpenRead(OriginalImagePath))
.Format(new WebPFormat())
.Quality(100)
.Save(webPFileStream);
}
}
Imageprocessor looks like a good library to convert the image. There is a Webp plugin.
Here is an article that may help.
Code example:
using ImageProcessor;
using ImageProcessor.Plugins.WebP.Imaging.Formats;
using (var normalFileStream = new FileStream(normalImagePath, FileMode.Create))
using (var webPFileStream = new FileStream(webPImagePath, FileMode.Create))
using (var imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(image.OpenReadStream())
.Format(new WebPFormat())
.Quality(50)
.Save(webPFileStream);
}
I'm developing a C# based application that requires to download, checkout, upload, check in on a specific file from/to Sharepoint with CSOM. So I have two questions here:
Firstly, on download, is there others way to download a specific named file under folder "Document" instead of searching through GetItemByID(). Please refer to code below:
string siteUrl = #"http://test.com/sites/company/";
ClientContext ctx = new ClientContext(siteUrl);
ctx.Credentials = new NetworkCredential("username", "password" , "domain");
ctx.AuthenticationMode = ClientAuthenticationMode.Default;
var list = ctx.Web.Lists.GetByTitle("Document");
var listItem = list.GetItemById();
ctx.Load(list);
ctx.Load(listItem, i => i.File);
ctx.ExecuteQuery();
var fileRef = listItem.File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(ctx, fileRef);
var fileName = Path.Combine("C:\\", (string)listItem.File.Name);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
Secondly, in regards to the workflow (download, modify, check out, upload, check in), is this feasible of doing?
Thanks in advance.
For getting specific file, no need to get ListItem by Id, instead, directly pass server relativer url like this:
ClientContext clientContext = new ClientContext("http://sp/sites/dev");
Web web = clientContext.Web;
Microsoft.SharePoint.Client.File filetoDownload = web.GetFileByServerRelativeUrl("/sites/dev/shared%20documents/mytest.txt");
clientContext.Load(filetoDownload);
clientContext.ExecuteQuery();
var fileRef = filetoDownload.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);
var fileName = Path.Combine("C:\\", (string)filetoDownload.Name);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
For other usage, checkout,update,checkin, I would suggest you can still use CSOM, as there are buit-in functions support:
File methods
I wanted to know how to download all documents from a SharePoint list using the SharePoint client object model (CSOM) (Microsoft.SharePoint.Client) and the lists full URL.
For example, if the URL was http://teamhub.myorg.local/sites/teams/it/ISLibrary/Guides/
Is it possible to connect directly to that URL and retrieve all documents stored there?
I have tried out the below code but I am getting an error, also it seems to require that I split the URL into two parts.
string baseURL = "http://teamhub.myorg.local/sites/";
string listURL = "teams/it/ISLibrary/Guides/";
var ctx = new ClientContext(baseURL);
ctx.Credentials = new SharePointOnlineCredentials(userName, SecuredpassWord);
var list = ctx.Web.GetList(listURL);
ctx.Load(list);
ctx.ExecuteQuery();
Console.WriteLine(list.Title);
When I run this code I simply get a "File not found" error.
Can it be done by simply passing in the full url somewhere?
I will need to do this connection and get all documents 100's of times over for many different lists, so it would be best if there is a way to do it using the full URL.
Any advice is appreciated. Thanks
Microsoft.SharePoint.Client.Web.GetListByUrl use webRelativeUrl, for example:
My site: https://tenant.sharepoint.com/sites/TST, library: https://tenant.sharepoint.com/sites/TST/MyDoc4
So the code would be:
Web web = clientContext.Web;
var lib=web.GetListByUrl("/MyDoc4");
The listURL you shared seems a folder, so we could get the folder and files in folder as below:
Web web = clientContext.Web;
Folder folder = web.GetFolderByServerRelativeUrl("/sites/TST/MyDoc4/Folder");
var files = folder.Files;
clientContext.Load(files);
clientContext.ExecuteQuery();
Download fileļ¼
foreach (var file in files)
{
clientContext.Load(file);
Console.WriteLine(file.Name);
ClientResult<Stream> stream = file.OpenBinaryStream();
clientContext.ExecuteQuery();
var fileOut = Path.Combine(localPath, file.Name);
if (!System.IO.File.Exists(fileOut))
{
using (Stream fileStream = new FileStream(fileOut, FileMode.Create))
{
CopyStream(stream.Value, fileStream);
}
}
}
private static void CopyStream(Stream src, Stream dest)
{
byte[] buf = new byte[8192];
for (; ; )
{
int numRead = src.Read(buf, 0, buf.Length);
if (numRead == 0)
break;
dest.Write(buf, 0, numRead);
}
}
I am creating a method to UploadDocument_FromStream() method which has one parameter -- Stream file.
I am having trouble trying to keep my SharePoint connection open to allow me to upload my Stream file to SharePoint. I think the issue is due to the fact that I am executing a query then trying to upload to SharePoint.
Is this the best way to handle Uploading to SharePoint with a MemoryStream?
UploadDocument_FromStream()
public void UploadDocument_FromStream(Stream file)
{
using (var clientContext = OpenConnectionToSharePoint())
{
if (file == null) throw new Exception("Stream cannot be null");
using (clientContext)
{
var list = clientContext.Web.Lists.GetByTitle("Documents");
clientContext.Load(list.RootFolder);
clientContext.ExecuteQuery();
Microsoft.SharePoint.Client.File.SaveBinaryDirect(clientContext, "/shared documents/test.pdf", file, true);
}
}
Also should note - that I am using SharePoint.Client.dll or COM approach.
SharePoint CSOM API utilizes internal query queue to support Request Batching via ClientRuntimeContext.Load method. But both File.OpenBinaryDirect and File.SaveBinaryDirect methods are executed directly and require internal queue to be empty. For that purpose you could utilize the following checking before invoking File.SaveBinaryDirect method:
if (ctx.HasPendingRequest)
ctx.ExecuteQuery();
The following example shows how to save a file stream into documents library
var list = ctx.Web.Lists.GetByTitle(listTitle);
ctx.Load(list.RootFolder);
ctx.ExecuteQuery();
var fileName = System.IO.Path.GetFileName(path);
byte[] data = System.IO.File.ReadAllBytes(path);
MemoryStream stream = new MemoryStream(data);
var fileUrl = Path.Combine(list.RootFolder.ServerRelativeUrl, fileName);
if (ctx.HasPendingRequest)
ctx.ExecuteQuery();
Microsoft.SharePoint.Client.File.SaveBinaryDirect(ctx, fileUrl, stream, true);