Access to sharepoint 2013 site from web api - c#

I'm working on a communication between a MVC web app developed in c# and typescript and a remote sharepoint site. I want to execute crud operations for an excel file.
I'm able to read site properties in this way:
public async Task<string> getWebTitle(string webUrl, string usr, string psw)
{
//Creating Password
const string PWD = psw;
const string USER = usr;
const string RESTURL = "{0}/_api/web?$select=Title";
//Creating Credentials
var passWord = new SecureString();
foreach (var c in PWD) passWord.AppendChar(c);
var credential = new SharePointOnlineCredentials(USER, passWord);
//Creating Handler to allows the client to use credentials and cookie
using (var handler = new HttpClientHandler() { Credentials = credential })
{
//Getting authentication cookies
Uri uri = new Uri(webUrl);
handler.CookieContainer.SetCookies(uri, credential.GetAuthenticationCookie(uri));
//Invoking REST API
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(string.Format(RESTURL, webUrl)).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
string jsonData = await response.Content.ReadAsStringAsync();
return jsonData;
}
}
}
jsonData object returns site properties.
How I can do to read a file, for example test.txt, saved in Documents folder in "mysite"?

Do you mean that you want to get the content of file in SharePoint?
We can use CSOM to achieve it.
Here is a sample for your reference:
public static void getContentOfFileInDocLib(string siteUrl, string host, string sourceListName, string fileName)
{
siteUrl = siteUrl.EndsWith("/") ? siteUrl.Substring(0, siteUrl.Length - 1) : siteUrl;
ClientContext context = new ClientContext(siteUrl);
Web web = context.Site.RootWeb;
List source = web.Lists.GetByTitle(sourceListName);
context.Load(source);
context.Load(web);
context.ExecuteQuery();
FileCollection files = source.RootFolder.Files;
Microsoft.SharePoint.Client.File file = files.GetByUrl(siteUrl + "/" + sourceListName + "/" + fileName);
context.Load(file);
context.ExecuteQuery();
FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, file.ServerRelativeUrl);
string filePath = host + file.ServerRelativeUrl;
System.IO.Stream fileStream = fileInfo.Stream;
FileCreationInformation createFile = new FileCreationInformation();
byte[] bufferByte = new byte[1024 * 100];
System.IO.MemoryStream memory = new System.IO.MemoryStream();
int len = 0;
while ((len = fileStream.Read(bufferByte, 0, bufferByte.Length)) > 0)
{
memory.Write(bufferByte, 0, len);
}
//we get the content of file here
byte[] bytes = memory.GetBuffer();
//do something you want
//.......
}
Upload file to SharePoint Document Library.
public static void uploadFile(string siteUrl, string filePath, string fileName, string docLibName)
{
siteUrl = siteUrl.EndsWith("/") ? siteUrl.Substring(0, siteUrl.Length - 1) : siteUrl;
ClientContext context = new ClientContext(siteUrl);
List docLib = context.Web.Lists.GetByTitle(docLibName);
context.Load(docLib);
context.ExecuteQuery();
Byte[] bytes = System.IO.File.ReadAllBytes(filePath + fileName);
FileCreationInformation createFile = new FileCreationInformation();
createFile.Content = bytes;
createFile.Url = siteUrl + "/" + docLibName + "/" + fileName;
createFile.Overwrite = true;
Microsoft.SharePoint.Client.File newFile = docLib.RootFolder.Files.Add(createFile);
newFile.ListItemAllFields.Update();
context.ExecuteQuery();
}

Related

Write content to a file on azure storage with using PUT request in C#

I am trying to make a put request to Azure storage file, where I want to add some simple contents. I change the URL and add ?comp=range at the end of the url but I get 403 error in response. I have created a basic console application in .net.
My Header is :
const string requestMethod = "PUT";
string urlPath = strShareName + "/" + "rahila.csv?comp=range";//+ "?comp=range HTTP/1.1";
String canonicalizedResource = String.Format("/{0}/{1}/{2}", StorageAccountName, strShareName, strFileName);
try
{
//GetWebRequest(requestMethod, urlPath, canonicalizedResource, "CreateFile");
HttpWebRequest request = null;
try
{
const string type = "file";
string MethodType = "CreateFile";
const string msVersion = "2015-04-05";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = "";
string data = "rahila sted";
canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
if (MethodType == "CreateFile")
{
canonicalizedHeaders = String.Format("x-ms-content-length:65536\nx-ms-date:{0}\nx-ms-type:file\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
}
String stringToSign = "";
stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
if (String.IsNullOrEmpty(stringToSign))
{
throw new ArgumentNullException("canonicalizedString");
}
String signature;
if (String.IsNullOrEmpty(stringToSign))
{
throw new ArgumentNullException("unsignedString");
}
if (Convert.FromBase64String(StorageKey) == null)
{
throw new ArgumentNullException("key");
}
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(stringToSign);
using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}",
StorageScheme,
StorageAccountName, signature);
Uri uri = new Uri(FileEndPoint + urlPath);
request = (HttpWebRequest)WebRequest.Create(uri);
if (requestMethod != "Get")
{
request.ContentLength = data.Length;
}
// string data = "Hello testing";
//int a= ((data.Length) + 1);
request.Method = "PUT";//requestMethod;
request.Headers.Add("x-ms-write", "update");
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", msVersion);
request.Headers.Add("x-ms-range", "bytes=0-65535"); // + ((data.Length) - 1));
request.Headers.Add("Authorization", authorizationHeader);
the line where i get the exception is in the bold format.
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
string returnString = response.StatusCode.ToString();
Can anyone help me to resolve this issue or just guide me how to write content to a simple file on azure storage without using the azure client API.
update 12/19:
When using Put Range to upload content to azure file, you can follow the following code(I assume you have already created a file on the azure file share, and it's content length is larger than the content being uploaded):
static void UploadText()
{
string Account = "xxxx";
string Key = "xxxx";
string FileShare = "test1";
string FileName = "11.txt";
string apiversion = "2019-02-02";
//the string to be uploaded to azure file, note that the length of the uploaded string should less than the azure file length
string upload_text = "bbbbbbbbbbbbbbbbbbbbbbbb.";
Console.WriteLine("the string length: " + upload_text.Length);
DateTime dt = DateTime.UtcNow;
string StringToSign = String.Format("PUT\n"
+ "\n" // content encoding
+ "\n" // content language
+ upload_text.Length + "\n" // content length
+ "\n" // content md5
+ "\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n"//+ "bytes=0-" + (upload_text.Length - 1) + "\n" // range
+"x-ms-date:" + dt.ToString("R") + "\nx-ms-range:bytes=0-"+(upload_text.Length-1) + "\nx-ms-version:" + apiversion + "\nx-ms-write:update\n" // headers
+ "/{0}/{1}/{2}\ncomp:range", Account, FileShare, FileName);
string auth = SignThis(StringToSign, Key, Account);
string method = "PUT";
string urlPath = string.Format("https://{0}.file.core.windows.net/{1}/{2}?comp=range", Account, FileShare,FileName);
Uri uri = new Uri(urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.ContentLength = upload_text.Length;
request.Headers.Add("x-ms-range", "bytes=0-"+(upload_text.Length-1));
request.Headers.Add("x-ms-write", "update");
request.Headers.Add("x-ms-date", dt.ToString("R"));
request.Headers.Add("x-ms-version", apiversion);
request.Headers.Add("Authorization", auth);
//request.Headers.Add("Content-Length", upload_text.Length.ToString());
var bytes = System.Text.Encoding.ASCII.GetBytes(upload_text);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
//read the content
Console.WriteLine("the response is:" + response.StatusCode);
}
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
Account,
signature);
return authorizationHeader;
}
Then in the Main() method, you can call UploadText() method, it works at my side.
old:
guide me how to write content to a simple file on azure storage
without using the azure client API.
For this, you can directly use Azure File Storage SDK Microsoft.Azure.Storage.File, version 11.1.1. And we always recommend using SDK instead of using rest api, because the SDK is easy to use.
Here is an example of using this SDK.
First, create a console project of .NET framework in visual studio. Then install this nuget package Microsoft.Azure.Storage.File, version 11.1.1.
The code:
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Auth;
using Microsoft.Azure.Storage.File;
using System;
namespace AzureFileTest2
{
class Program
{
static void Main(string[] args)
{
string accountName = "xxx";
string accountKey = "xxx";
CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudFileClient cloudFileClient = storageAccount.CreateCloudFileClient();
//make sure the file share named test1 exists.
CloudFileShare fileShare = cloudFileClient.GetShareReference("test1");
CloudFileDirectory fileDirectory = fileShare.GetRootDirectoryReference();
CloudFile myfile = fileDirectory.GetFileReference("test123.txt");
if (!myfile.Exists())
{
//if the file does not exists, then create the file and set the file max size to 100kb.
myfile.Create(100 * 1024 * 1024);
}
//upload text to the file
//Besides using UploadText() method to directly upload text, you can also use UploadFromFile() / UploadFromByteArray() / UploadFromStream() methods as per your need.
myfile.UploadText("hello, it is using azure storage SDK");
Console.WriteLine("**completed**");
Console.ReadLine();
}
}
}

How to create folders in google drive without duplicate using c#?

I am trying to create a folder on my google drive and check if it already exists. I am new to c#, so I wrote a code to create a specific folder in which I can upload my CSV files, but each time my application runs, it creates a duplicate folder with same name and I am now trying to figure out how to stop it.
class GoogleApi
{
private string[] Scopes = { DriveService.Scope.Drive };
private string ApplicationName;
private string FolderId;
private string FileName;
private string FilePath;
private string ContentType;
public GoogleApi(string fileName, string filePath)
{
ApplicationName = "MantisToDrive";
ContentType = "text/csv";
FileName = fileName;
FilePath = filePath;
}
public void Upload()
{
UserCredential credential = GetCredentials();
DriveService service = GetDriveService(credential);
FolderId = CreateFolderToDrive(service, "MantisData");
UploadFileToDrive(service, FileName, FilePath, ContentType);
}
private DriveService GetDriveService(UserCredential credential)
{
return new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
}
//verify User Credentials using client_secret.json file
private UserCredential GetCredentials()
{
UserCredential credential;
using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath , true)).Result;
}
return credential;
}
private string UploadFileToDrive(DriveService service, string fileName, string filePath, string contentType)
{
var fileMatadata = new Google.Apis.Drive.v3.Data.File();
fileMatadata.Name = fileName;
fileMatadata.Parents = new List<string> { FolderId };
FilesResource.CreateMediaUpload request;
using (var stream = new FileStream(filePath, FileMode.Open))
{
request = service.Files.Create(fileMatadata, stream, contentType);
//service.Files.Delete(fileName).Execute();
request.Upload();
}
var file = request.ResponseBody;
return file.Id;
}
// creating folder in google drive to store CSV
public static string CreateFolderToDrive(DriveService service, string folderName)
{
bool exists = Exists(service,folderName);
if (exists)
return $"Sorry but the file {folderName} already exists!";
var file = new Google.Apis.Drive.v3.Data.File();
file.Name = folderName;
file.MimeType = "application/vnd.google-apps.folder";
var request = service.Files.Create(file);
request.Fields = "id";
var result = request.Execute();
return result.Id;
}
private static bool Exists(DriveService service, string name)
{
var listRequest = service.Files.List();
listRequest.PageSize = 100;
listRequest.Q = $"trashed = false and name contains '{name}' and 'root' in parents";
listRequest.Fields = "files(name)";
var files = listRequest.Execute().Files;
foreach (var file in files)
{
if (name == file.Name)
return true;
}
return false;
}
}
This should work (this checks whether the folder exists in your root folder. If not, the method will create a folder):
public static string CreateFolder(string folderName)
{
bool exists = Exists(folderName);
if (exists)
return $"Sorry but the file {folderName} already exists!";
var file = new Google.Apis.Drive.v3.Data.File();
file.Name = folderName;
file.MimeType = "application/vnd.google-apps.folder";
var request = service.Files.Create(file);
request.Fields = "id";
return request.Execute().Id;
}
private static bool Exists(string name)
{
var listRequest = service.Files.List();
listRequest.PageSize = 100;
listRequest.Q = $"trashed = false and name contains '{name}' and 'root' in parents";
listRequest.Fields = "files(name)";
var files = listRequest.Execute().Files;
foreach (var file in files)
{
if (name == file.Name)
return true;
}
return false;
}
In case somebody comes here from the future and the pastebin link is dead. This is how you can upload a file to your google drive:
public static async Task UploadFileAsync(string fileName)
{
var file = new Google.Apis.Drive.v3.Data.File();
file.Name = Path.GetFileName(fileName);
file.Parents = new List<string> {folderID};
byte[] byteArray = System.IO.File.ReadAllBytes(fileName);
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray))
{
await service.Files.Create(file, stream, "some mime type").UploadAsync();
}
}

Download Objects from S3 Bucket using c#

Im trying to download object from S3 bucket facing below issue
The Security token included in the request is Invalid .
Please check and correct where is the mistake.
Below is my code
1. Get Temporary credentails:
main()
{
string path = "http://XXX.XXX.XXX./latest/meta-data/iam/security-credentials/EC2_WLMA_Permissions";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path);
request.Method = "GET";
request.ContentType = "application/json";
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
dynamic metaData = JsonConvert.DeserializeObject(result);
_awsAccessKeyId = metaData.AccessKeyId;
_awsSecretAccessKey = metaData.SecretAccessKey;
}
}
Create SessionAWSCredentials instance:
SessionAWSCredentials tempCredentials =
GetTemporaryCredentials(_awsAccessKeyId, _awsSecretAccessKey);
//GetTemporaryCredentials method:
private static SessionAWSCredentials GetTemporaryCredentials(
string accessKeyId, string secretAccessKeyId)
{
AmazonSecurityTokenServiceClient stsClient =
new AmazonSecurityTokenServiceClient(accessKeyId,
secretAccessKeyId);
Console.WriteLine(stsClient.ToString());
GetSessionTokenRequest getSessionTokenRequest =
new GetSessionTokenRequest();
getSessionTokenRequest.DurationSeconds = 7200; // seconds
GetSessionTokenResponse sessionTokenResponse =
stsClient.GetSessionToken(getSessionTokenRequest);
Console.WriteLine(sessionTokenResponse.ToString());
Credentials credentials = sessionTokenResponse.Credentials;
Console.WriteLine(credentials.ToString());
SessionAWSCredentials sessionCredentials =
new SessionAWSCredentials(credentials.AccessKeyId,
credentials.SecretAccessKey,
credentials.SessionToken);
return sessionCredentials;
}
Get files from S3 using AmazonS3Client:
using (IAmazonS3 client = new AmazonS3Client(tempCredentials,RegionEndpoint.USEast1))
{
GetObjectRequest request = new GetObjectRequest();
request.BucketName = "bucketName" + #"/" + "foldername";
request.Key = "Terms.docx";
GetObjectResponse response = client.GetObject(request);
response.WriteResponseStreamToFile("C:\\MyFile.docx");
}
We do something a little simpler for interfacing with S3 (downloads and uploads)
It looks like you went the more complex approach. You should try just using the TransferUtility instead:
TransferUtility fileTransferUtility =
new TransferUtility(
new AmazonS3Client("ACCESS-KEY-ID", "SECRET-ACCESS-KEY", Amazon.RegionEndpoint.CACentral1));
// Note the 'fileName' is the 'key' of the object in S3 (which is usually just the file name)
fileTransferUtility.Download(filePath, "my-bucket-name", fileName);
NOTE: TransferUtility.Download() returns void because it downloads the file to the path specified in the filePath argument. This may be a little different than what you were expecting but you can still open a FileStream to that path afterwards and manipulate the file all you want. For example:
using (FileStream fileDownloaded = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// Do stuff with our newly downloaded file
}
Bucketname, Accesskey and secretkey, I took from web config. You could type manually.
public void DownloadObject(string imagename)
{
RegionEndpoint bucketRegion = RegionEndpoint.USEast1;
IAmazonS3 client = new AmazonS3Client(bucketRegion);
string accessKey = System.Configuration.ConfigurationManager.AppSettings["AWSAccessKey"];
string secretKey = System.Configuration.ConfigurationManager.AppSettings["AWSSecretKey"];
AmazonS3Client s3Client = new AmazonS3Client(new BasicAWSCredentials(accessKey, secretKey), Amazon.RegionEndpoint.USEast1);
string objectKey = "EMR" + "/" + imagename;
//EMR is folder name of the image inside the bucket
GetObjectRequest request = new GetObjectRequest();
request.BucketName = System.Configuration.ConfigurationManager.AppSettings["bucketname"];
request.Key = objectKey;
GetObjectResponse response = s3Client.GetObject(request);
response.WriteResponseStreamToFile("D:\\Test\\"+ imagename);
}
//> D:\Test\ is local file path.
Following is how I download it. I need to download only .zip files in this case. Restricting to only required file types (.zip in my case), helped me to avoid errors related to (416) Requested Range Not Satisfiable
public static class MyAWS_S3_Helper
{
static string _S3Key = System.Configuration.ConfigurationManager.ConnectionStrings["S3BucketKey"].ConnectionString;
static string _S3SecretKey = System.Configuration.ConfigurationManager.ConnectionStrings["S3BucketSecretKey"].ConnectionString;
public static void S3Download(string bucketName, string _ObjectKey, string downloadPath)
{
IAmazonS3 _client = new AmazonS3Client(_S3Key, _S3SecretKey, Amazon.RegionEndpoint.USEast1);
TransferUtility fileTransferUtility = new TransferUtility(_client);
fileTransferUtility.Download(downloadPath + "\\" + _ObjectKey, bucketName, _ObjectKey);
_client.Dispose();
}
public static async Task AsyncDownload(string bucketName, string downloadPath, string requiredSunFolder)
{
var bucketRegion = RegionEndpoint.USEast1; //Change it
var credentials = new BasicAWSCredentials(_S3Key, _S3SecretKey);
var client = new AmazonS3Client(credentials, bucketRegion);
var request = new ListObjectsV2Request
{
BucketName = bucketName,
MaxKeys = 1000
};
var response = await client.ListObjectsV2Async(request);
var utility = new TransferUtility(client);
foreach (var obj in response.S3Objects)
{
string currentKey = obj.Key;
double sizeCheck = Convert.ToDouble(obj.Size);
int fileNameLength = currentKey.Length;
Console.WriteLine(currentKey + "---" + fileNameLength.ToString());
if (currentKey.Contains(requiredSunFolder))
{
if (currentKey.Contains(".zip")) //This helps to avoid errors related to (416) Requested Range Not Satisfiable
{
try
{
S3Download(bucketName, currentKey, downloadPath);
}
catch (Exception exTest)
{
string messageTest = currentKey + "-" + exTest;
}
}
}
}
}
}
Here is how it is called
static void Main(string[] args)
{
string downloadPath = #"C:\SourceFiles\TestDownload";
Task awsTask = MyAWS_S3_Helper.AsyncDownload("my-files", downloadPath, "mysubfolder");
awsTask.Wait();
}
Here is what I have done to download the files from S3 bucket,
var AwsImportFilePathParcel = "TEST/TEMP"
IAmazonS3 client = new AmazonS3Client(AwsAccessKey,AwsSecretKey);
S3DirectoryInfo info = new S3DirectoryInfo(client, S3BucketName, AwsImportFilePathParcel);
S3FileInfo[] s3Files = info.GetFiles(pattenForParcel);
now in s3Files, you have all the files which are on provided location, using for each you can save all files in to your system
foreach (var fileInfo in s3Files)
{
var localPath = Path.Combine("C:\TEST\", fileInfo.Name);
var file = fileInfo.CopyToLocal(localPath);
}

How to upload a file to a document library in sharepoint?

I have a byte[] data and I want to upload it to sharepoint site using c#. I also want to pass credentials for it. Can anyone please guide me.
The code I tried is:
Uri destUri = new Uri("http://test.net/excel/docs/Forms/AllItems.aspx/");
WebRequest req = WebRequest.Create(destUri);
req.Method = "PUT";
req.Credentials = CredentialCache.DefaultCredentials;
using (req.GetRequestStream())
{
string destFilename = #"\\test.net\excel\docs\501.xls";
byte[] data = new byte[10];
System.IO.File.WriteAllBytes(destFilename, data);
}
ERROR:
Access Denied
Current user should have add permissions on this library
public void UploadFileToDocmentLibrary(Byte[] contentArray)
{
using (SPSite sharePointtopLevelSite = new SPSite("http://localhost"))
{
SPWeb websiteCollection = sharePointtopLevelSite.AllWebs["webName"];
websiteCollection.AllowUnsafeUpdates = true;
websiteCollection.Lists.IncludeRootFolder = true;
SPList docLibrary = websiteCollection.Lists["listName"];
SPFile file = websiteCollection.Files.Add(websiteCollection.Url.ToString() + "/" + docLibrary.Title.ToString() + "/" + "fileName.ext", contentArray);
file.Update();
}
}
If user without permissions should do it, use RunWithElevatedPrivileges statement
If I understood your requirements properly, you need to upload file into SharePoint On-Premise, right? There are several options on how to accomplish it.
Send file via HTTP POST using .NET
At least the following components could be utilized for that purpose:
HttpWebRequest
WebClient
HttpClient
Example
The example demonstrates how to upload file using WebClient.UploadFile Method:
public static void UploadFile(Uri targeUri, ICredentials credentials, string fileName)
{
using (var client = new WebClient())
{
client.Credentials = credentials;
//client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
var targetFileUri = targeUri + "/" + Path.GetFileName(fileName);
client.UploadFile(targetFileUri, "PUT", fileName);
}
}
Usage
var filePath = #"C:\Documents\SharePoint User Guide.docx";
var credentials = new NetworkCredential(userName, password, domain);
UploadFile(new Uri("https://contoso.sharepoint.com/documents"),credentials, filePath);
Using Microsoft SharePoint Server Object Model
using (var site = new SPSite(url))
{
using (var web = site.OpenWeb())
{
var list = web.Lists.TryGetList(listTitle);
var targetFolder = list.RootFolder;
var fileContent = System.IO.File.ReadAllBytes(fileName);
var fileUrl = Path.GetFileName(fileName);
targetFolder.Files.Add(fileUrl, fileContent);
}
}
Using Microsoft SharePoint Client Object Model
SharePoint 2010 Client Components SDK
SharePoint 2013 Client Components SDK
How to upload a file to a SharePoint site using File.SaveBinaryDirect Method
using (var ctx = new ClientContext(url))
{
ctx.Credentials = new NetworkCredential(userName, password, domain);
using (var fs = new FileStream(fileName, FileMode.Open))
{
var fi = new FileInfo(fileName);
var list = ctx.Web.Lists.GetByTitle(listTitle);
ctx.Load(list.RootFolder);
ctx.ExecuteQuery();
var fileUrl = String.Format("{0}/{1}", list.RootFolder.ServerRelativeUrl, fi.Name);
Microsoft.SharePoint.Client.File.SaveBinaryDirect(ctx, fileUrl, fs, true);
}
}
Using SharePoint Web Services
How to upload file using Copy Web Service:
var webUri = new Uri("http://contoso.sharepoint.com");
string sourceUrl = #"C:\Documents\SharePoint User Guide.docx";
string destinationUrl = webUri + "/documents/SharePoint User Guide 2013.docx";
var fieldInfo = new FieldInformation();
FieldInformation[] fieldInfos = { fieldInfo };
CopyResult[] result;
using (var proxyCopy = new Copy())
{
proxyCopy.Url = webUri + "/_vti_bin/Copy.asmx";
proxyCopy.Credentials= new NetworkCredential(userName, password, domain);
var fileContent = System.IO.File.ReadAllBytes(sourceUrl);
proxyCopy.CopyIntoItems(sourceUrl, new[] { destinationUrl }, fieldInfos, fileContent, out result);
}

How to stream file upload in C# Web Api for database storage

I've spent hours working many found examples without success for what is super simple to do in a web forms application. That is, upload one or more files and store them in sql server.
In web forms (vb.net) I can do this:
Dim fs As Stream = fileUpload1.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "INSERT INTO files ([name], [type], [file]) VALUES (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value() = contenttype
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
Then do the database execute statements......done!
Now C# Web-Api:
The seemingly good example I have now that saves uploads to the filesystem via Web-Api is:
public Task<IEnumerable<FileDesc>> Old()
{
string folderName = "uploads";
string PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
if (Request.Content.IsMimeMultipartContent())
{
var streamProvider = new MultipartFormDataStreamProvider(PATH);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
return new FileDesc(info.Name, rootUrl + "/" + folderName + "/" + info.Name, info.Length / 1024);
});
return fileInfo;
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
I cannot seem to figure out how to get each multipart file content stream so that I can send to the database. I've seen posts talking about MultipartMemoryStreamProvider and MultipartStreamProvider but I haven't figured out how to use them. I'm clearly over my head as a C# and Web-Api newbie.
Can anyone direct me on how to get the file contents into a stream I can get the bytes to send to the db?
Here's my solution when I encountered this issue:
Client:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}
Controller:
public async Task<HttpResponseMessage> Post()
{
Stream requestStream = await this.Request.Content.ReadAsStreamAsync();
byte[] byteArray = null;
using (MemoryStream ms = new MemoryStream())
{
await requestStream.CopyToAsync(ms);
byteArray = ms.ToArray();
}
.
.
.
return Request.CreateResponse(HttpStatusCode.OK);
}

Categories