Read SharePoint List Item Attachment (image) and Convert Into Base64 String Using CSOM Through App Only Authentication

Introduction

 
According to one of our requirements, there was a public-facing site developed in .NET core and retrieving data from a SharePoint list. To authenticate it with SharePoint, we were using SharePoint App only authentication. So, for one feature we need to get SharePoint list item attachment (which will always be image file) and display it on a .NET core site.
 

Problem Statement

 
We cannot directly add a URL SharePoint list item attachment in the src attribute of the img tag. This is because a .NET application cannot be authenticated directly with SharePoint.
 

Solution

 
We have created a web API which will return base64 string of image attached with a SharePoint list item and we will use this base64 string to display an image on a public-facing site developed in .NET core.
 
Note
.NET core is still not supported in the CSOM library, so we have created a web API solution to interact with SharePoint list items.
 
Step 1
 
Create web API which will authenticate with SharePoint through app-only authentication and fetch list item attachment.
 
Then convert this attachment in base64 string and return this base64 string with JSON format.
 
Below is code for the web API:  
  1. [HttpGet]  
  2. [Route("GetProjects")]  
  3. public JsonResult Get()  
  4. {  
  5.    string clientID = "**************";  
  6.    string clientSecret = "*********************";  
  7.    string siteUrl = "https://********.sharepoint.com/sites/*****";  
  8.    JsonResult jsRes = new JsonResult();  
  9.    ListItemCollection items;  
  10.    List<projectsData> Data = new List<projectsData>();  
  11.    using (var clientContext = new AuthenticationManager().GetAppOnlyAuthenticatedContext(siteUrl, clientID, clientSecret))  
  12.    {  
  13.       List projectsList = clientContext.Web.Lists.GetByTitle("Projects");  
  14.       CamlQuery query = CamlQuery.CreateAllItemsQuery(100);  
  15.   
  16.       items = projectsList.GetItems(query);  
  17.   
  18.       clientContext.Load(items);  
  19.       clientContext.ExecuteQuery();  
  20.       projectsData project = new projectsData();  
  21.       foreach (ListItem listItem in items)  
  22.       {  
  23.          project = new projectsData();  
  24.          project.ProjectTitle = Convert.ToString(listItem["Title"]);  
  25.          project.ProjectID = listItem.Id;  
  26.         //Get list attachments  
  27.          AttachmentCollection oAttachments = listItem.AttachmentFiles;  
  28.          clientContext.Load(oAttachments);  
  29.          clientContext.ExecuteQuery();  
  30.          string imgBase64Str = "";  
  31.          if (oAttachments.Count > 0)  
  32.          {  
  33.             Attachment oAttachment = oAttachments[0];  
  34.             var file = clientContext.Web.GetFileByServerRelativeUrl(oAttachment.ServerRelativeUrl);  
  35.             clientContext.Load(file);  
  36.             clientContext.ExecuteQuery();  
  37.             ClientResult<System.IO.Stream> data = file.OpenBinaryStream();  
  38.             clientContext.Load(file);  
  39.             clientContext.ExecuteQuery();  
  40.             using (System.IO.MemoryStream mStream = new System.IO.MemoryStream())  
  41.             {  
  42.                if (data != null)  
  43.                {  
  44.                   data.Value.CopyTo(mStream);  
  45.                   byte[] imageArray = mStream.ToArray();  
  46.                   imgBase64Str = Convert.ToBase64String(imageArray);  
  47.                }  
  48.             }  
  49.        }  
  50.   
  51.        project.imgBase64String = imgBase64Str;  
  52.        Data.Add(project);         
  53.        }  
  54.    };  
  55.    string result = JsonConvert.SerializeObject(Data);  
  56.    return jsRes = new JsonResult  
  57.    {  
  58.        Data = result  
  59.    };  
  60. }  
Here is code of class which we have used in above code snippet,
  1. public class ProjectDetails  
  2. {  
  3.    public string ProjectTitle { getset; }  
  4.    public int ProjectID { getset; }  
  5.    public string ImgBase64String { getset; }  
  6. }  
Step 2
 
Now we will use this web API in our .NET core solution.
 
Here is the code snippet for using the web API created in Step 1:
  1. public async Task<IActionResult> HomeAsync()  
  2. {  
  3.    List<ProjectDetails> reservationList = new List<ProjectDetails>();  
  4.    using (var httpClient = new System.Net.Http.HttpClient())  
  5.    {  
  6.       using (var response = await httpClient.GetAsync("https://*********.azurewebsites.net/GetProjects"))  
  7.       {  
  8.          string apiResponse = await response.Content.ReadAsStringAsync();  
  9.          var jsonResult = JObject.Parse(apiResponse);  
  10.          apiResponse = jsonResult["Data"].ToString();  
  11.          reservationList = JsonConvert.DeserializeObject<List<ProjectDetails>>(apiResponse);  
  12.       }  
  13.    }  
  14. return View(reservationList);  
  15. }  
Here is the model used in the above code snippet.
  1. public class ProjectDetails  
  2. {  
  3.    public string ProjectTitle { getset; }  
  4.    public int ProjectID { getset; }  
  5.    public string ImgBase64String { getset; }  
  6. }  
Step 3
 
In the above step, we have stored a base64 string in the model. So now, we will use this base64 string to display the image below.
 
Here is how we will use this base64 string to display an image using an img tag.
  1. <img src="data:image/jpeg;base64,@item.ImgBase64String" alt="Image not available ">  
Note
Here in this article, we are targetting an image file as an attachment, but we can use the same code to get the base64 string of other file types.
 
Hope this article will help you.