ASP.NET Custom Web API & Curl Bash and PowerShell commands to download files from SharePoint Online

In this article I am going to illustrate how to download a file from SharePoint Online using Custom ASP.NET Web API and Curl Bash Command.

Model Definition

using System.ComponentModel.DataAnnotations;
using SPOL.FileDownload.Filters;

namespace SPOL.FileDownload.Models
{
public class SPOLFile
{
[Required(ErrorMessage = “Site Url is not passed with the endpoint”)]
[Display(Name = “SiteUrl”)]
[ValidateSite]
public string SiteUrl { get; set; }

[Required(ErrorMessage = “Library Name is not passed with the endpoint”)]
[Display(Name = “LibraryName”)]
[ValidateLibrary]
public string LibraryName { get; set; }

[Display(Name = “FolderPath”)]
[ValidateFolder]
public string FolderPath { get; set; }

[Required(ErrorMessage = “File Name is not passed with the endpoint”)]
[Display(Name = “FileName”)]
[ValidateFile]
public string FileName { get; set; }
}
}

Model Validation

using System.Net;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace SPOL.FileDownload.Filters
{
public class ValidateSPOSiteModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.ModelState.IsValid == false)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(
HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
}

Model Field Validation

using System.ComponentModel.DataAnnotations;
using SPOL.FileDownload.Helpers;
using Microsoft.SharePoint.Client;

namespace SPOL.FileDownload.Filters
{
public class ValidateSiteAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
try
{
ClientContext clientContext = null;
var url = value as string;

if (string.IsNullOrEmpty(url))
return false;

clientContext = new OfficeDevPnP.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant(url, Settings.serviceAccountUserId, Settings.serviceAccountPassword);
var web = clientContext.Web;
clientContext.Load(web);

try
{
clientContext.ExecuteQuery();
return true;
}
catch
{
ErrorMessage = “Site url you have passed in not valid.”;
return false;
}
finally
{
if (clientContext != null)
clientContext.Dispose();
}
}
catch
{
ErrorMessage = “There is a problem accessing the site url.”;
return false;
}
}

}
}

Model Field Validation with Validation Context to pass parameters

using System.ComponentModel.DataAnnotations;
using SPOL.FileDownload.Helpers;
using Microsoft.SharePoint.Client;
using System;
using System.Reflection;
using System.IO;

namespace SPOL.FileDownload.Filters
{
public class ValidateFileAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
bool isValid = true;
string ErrorMessage = "";
ClientContext clientContext = null;

try
{

var filename = value as string;

object instance = validationContext.ObjectInstance;
Type type = instance.GetType();

PropertyInfo propertySiteUrl = type.GetProperty("SiteUrl");
PropertyInfo propertyLibraryName = type.GetProperty("LibraryName");
PropertyInfo propertyFolderPath = type.GetProperty("FolderPath");

object siteUrl = propertySiteUrl.GetValue(instance);
object libraryName = propertyLibraryName.GetValue(instance);
object objFolderPath = propertyFolderPath.GetValue(instance);

string folderpath = Convert.ToString(string.IsNullOrEmpty((string)objFolderPath) ? "" : objFolderPath);

if (string.IsNullOrEmpty(filename))
{
isValid = false;
ErrorMessage = "File name is not passed with the endpoint";
}

string extention = Path.GetExtension(filename);

if (string.IsNullOrEmpty(extention))
{
ErrorMessage = "Not a valid file name extention.";
isValid = false;
}
else
{

clientContext = new OfficeDevPnP.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant(siteUrl.ToString(), Settings.serviceAccountUserId, Settings.serviceAccountPassword);

var url = new Uri(siteUrl.ToString());
var relativeUrl = String.Format("{0}/{1}/{2}/{3}", url.AbsolutePath, libraryName.ToString(), folderpath, filename);

try
{
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, relativeUrl);
isValid = true;
}
catch
{
ErrorMessage = "File name you have passed in not avilable.";
isValid = false;
}
finally
{
if (clientContext != null)
clientContext.Dispose();
}
}
}
catch
{
ErrorMessage = "There is a problem accessing the file.";
isValid = false;
}

if (isValid)
return ValidationResult.Success;
else
return new ValidationResult(ErrorMessage);
}
}
}

Controller

using SPOL.FileDownload.Filters;
using SPOL.FileDownload.Helpers;
using SPOL.FileDownload.Models;
using Microsoft.SharePoint.Client;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;

namespace SPOL.FileDownload.Controllers
{
public class DownloadFileController : ApiController
{
[Route(“api/file”)]
[HttpGet]
[ValidateSPOSiteModel]
public HttpResponseMessage DownloadFile([FromUri] SPOLFile spolFile)
{
MemoryStream stream = new MemoryStream();
ClientContext clientContext = null;

try
{
if (ModelState.IsValid)
{
clientContext = new OfficeDevPnP.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant(spolFile.SiteUrl, Settings.serviceAccountUserId, Settings.serviceAccountPassword);

var url = new Uri(spolFile.SiteUrl);
var relativeUrl = String.Format(“{0}/{1}/{2}/{3}”, url.AbsolutePath, spolFile.LibraryName, spolFile.FolderPath, spolFile.FileName);

var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, relativeUrl);

var buf = new byte[1024 * 16];
int byteSize;

while ((byteSize = fileInfo.Stream.Read(buf, 0, buf.Length)) > 0)
{
stream.Write(buf, 0, byteSize);
}

string mediaType = MimeMapping.GetMimeMapping(spolFile.FileName);

var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(stream.ToArray());
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(“attachment”);
result.Content.Headers.ContentDisposition.FileName = spolFile.FileName;
result.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType);

return result;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.ToString()); // new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
finally
{
if (stream != null)
stream.Dispose();
if (clientContext != null)
clientContext.Dispose();
}
}

}
}

 

Bash Command

endpoint='http://site.azurewebsites.net/api/file'
siteurl='https://site.sharepoint.com/sites/dev'
libraryname='Files to Download'
folderpath='First Level/Second Level'
filename='Azure_Application_Insights.pptx'

url=”${endpoint}?siteurl=${siteurl}&libraryname=${libraryname}&folderpath=${folderpath}&filename=${filename}”

curl “${url}” -o “${filename}”
PowerShell Command
The same operation can be done in windows OS using PowerShell commands as well.

Invoke-RestMethod -Uri "http://site.azurewebsites.net/api/file?siteurl=https://site.sharepoint.com/sites/dev&libraryname=Files to Download&folderpath=&filename=Azure_Application_Insights.pptx" -Method Get | Out-File -filepath "C:\Users\joseph\Downloads\Azure_Application_Insights.pptx"

Advertisements

About Joseph Velliah
As a SharePoint Developer my professional interests tend to be technical and SharePoint focused. I run a blog at "SP RIDER" where you can expect to read HOW TOs and scenarios that I run into during my day to day job. I hope my posts will give back a little to the community that is helped me.

Comments are closed.

%d bloggers like this: