I am trying to download a file from a client Sharepoint site. I am using sharepoint CSOM.
My code is as follows:
using Microsoft.SharePoint.Client;
var username = "username";
var password = "pass";
var url = "https://myclient.sharepoint.com/";
var fileurl = "https://myclient.sharepoint.com/teams/folder1/folder%20x/somefile.docx";
using (ClientContext context = new ClientContext(url))
{
SecureString passWord = new SecureString();
foreach (char c in password.ToCharArray()) passWord.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials(username, passWord);
Uri filename = new Uri(fileurl);
string server = filename.AbsoluteUri.Replace(filename.AbsolutePath, "");
string serverrelative = filename.AbsolutePath;
Microsoft.SharePoint.Client.File file = context.Web.GetFileByServerRelativeUrl(serverrelative);
context.Load(file);
ClientResult<Stream> streamResult = file.OpenBinaryStream();
context.ExecuteQuery();
var file2 = streamResult.Value;
}
The problem is that I get access denied, yet when I log in with the same credentials, I can download the file successfully.
Is there a separate permission in Sharepoint for downloading file from API instead of UI?
Could the space in the folder name be the problem?
UPDATE
Verified this does not have anything to do with spaces in folder or filename.
In case if SharePoint site uses multiple authentication providers using a set of Windows credentials (also relevant for SharePoint Online), the additional header must be included in a request: X-FORMS_BASED_AUTH_ACCEPTED with a value of f
For ClientContext class the header could be included like this:
ctx.ExecutingWebRequest += (sender, e) =>
{
e.WebRequestExecutor.WebRequest.Headers["X-FORMS_BASED_AUTH_ACCEPTED"] = "f";
};
Example
var file = ctx.Web.GetFileByUrl(fileAbsUrl);
ctx.Load(file);
var streamResult = file.OpenBinaryStream();
ctx.ExecuteQuery();
//save into file
using (var fileStream = System.IO.File.Create(#"C:\path\filename.docx"))
{
streamResult.Value.Seek(0, SeekOrigin.Begin);
streamResult.Value.CopyTo(fileStream);
}
Note: instead of converting to relative url, GetFileByUrl
method is used which accepts absolute url
Problem was that I was not connecting to the right url (new ClientContext(url))
I was connecting to: https://myclient.sharepoint.com/
I should have been connecting to: https://myclient.sharepoint.com/teams/folder1/
Related
I have a C# desktop app which allows the user to backup its to google drive via the google drive api V3.
I have the following method in a class which is used to load the backups
static string[] Scopes = { DriveService.Scope.DriveFile };
static string ApplicationName = "MyApp";
private static string CreateFile(string pFilePath, string parentFolderId, DriveService service)
{
var fileMetaData = new Google.Apis.Drive.v3.Data.File();
fileMetaData.Name = Path.GetFileName(pFilePath);
fileMetaData.MimeType = "application/vnd.google-apps.file";
fileMetaData.Parents = new List<string> { parentFolderId };
FilesResource.CreateMediaUpload request;
using(var stream = new FileStream(pFilePath, FileMode.Open))
{
request = service.Files.Create(fileMetaData, stream, "application/vnd.google-apps.file");
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
return file.Id;
}
Upon reaching request.Upload(), the request doesn't seem to have any issues, but later on after the file declaration, file turns out to be null, so no response body and thus no id either.
Is there something wrong with my request? I tried to see if I could catch an Exception in upload, which the method description claims would be of type IUploadProgress.Exception, but such an interface doesn't actually have an Exception property.
I've already authenticated and I managed to create a folder (which is the ID passed by argument parentFolderId, confirmed to not be null), so I am able to communicate with drive, just that this particular upload isn't working.
This is the code i use How to upload a file to Google Drive with C# .net I use the async method personally
string uploadedFileId;
// Create a new file on Google Drive
await using (var fsSource = new FileStream(UploadFileName, FileMode.Open, FileAccess.Read))
{
// Create a new file, with metadata and stream.
var request = service.Files.Create(fileMetadata, fsSource, "text/plain");
request.Fields = "*";
var results = await request.UploadAsync(CancellationToken.None);
if (results.Status == UploadStatus.Failed)
{
Console.WriteLine($"Error uploading file: {results.Exception.Message}");
}
// the file id of the new file we created
uploadedFileId = request.ResponseBody?.Id;
}
As for your code i think you need execute on the end
request.Upload().Execute;
I'm trying to upload an image file to aws s3 storage and get back that image URL. I'm using secret key and access key to create credentials. But when the program runs it it says
"Unable to find credentials" .
Here is my code which i used.
public string sendMyFileToS3(string from,string to, string bucketName, string fileName)
{
BasicAWSCredentials awsCreds = new BasicAWSCredentials(bucketName, fileName);
AmazonS3Client client = new AmazonS3Client(awsCreds);
TransferUtility utility = new TransferUtility(client);
TransferUtilityUploadRequest request = new TransferUtilityUploadRequest();
request.BucketName = bucketName;
request.Key = fileName;
request.FilePath = from;
utility.Upload(request);
string urlString = "";
GetPreSignedUrlRequest request1 = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = fileName,
Expires = DateTime.Now.AddYears(2)
};
urlString = client.GetPreSignedURL(request1);
Console.WriteLine(urlString);
File.Move(from, to);
return urlString ;
}
In order to create an S3 Client you need to provide your credentials, the region and endpoint:
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3Config config = new AmazonS3Config();
config.ServiceURL = "s3.amazonaws.com";
config.RegionEndpoint = Amazon.RegionEndpoint.GetBySystemName("us-east-1");
client = new AmazonS3Client(credentials, config);
The possible regions are listed here, and depend on where you created your bucket being us-east-1 the default value.
While the possible endpoints are this three:
s3.amazonaws.com
s3-accelerate.amazonaws.com
s3-accelerate.dualstack.amazonaws.com
The first one being the standard one since the others need you to configure your bucket like it's explained here.
I am going to take a guess and say you have a conflict between the credentials your app is using and other credentials you may have installed onto your dev or test machine, i.e. in the credentials file or your app.config.
I would check and make sure you are only using a single method to provide those credentials to the program.
THis link shows the priority the SDK will look for the credentials:
http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html
I am trying to perform a Sharepoint Online search using the C# API:
var clientContext =
new ClientContext("https://foobar.sharepoint.com/_layouts/15/start.aspx#/Shared%20Documents");
var pw = "apassword";
var secure = new SecureString();
foreach (var c in pw) secure.AppendChar(c);
var credentials = new SharePointOnlineCredentials("adress#mail.com", secure);
clientContext.Credentials = credentials;
var keywordQuery = new KeywordQuery(clientContext);
keywordQuery.QueryText = "SharePoint";
var searchExecutor = new SearchExecutor(clientContext);
var results = searchExecutor.ExecuteQuery(keywordQuery);
clientContext.ExecuteQuery();
I get the response '401: Unauthorized', although the credentials I've provided are correct. What am I missing here?
You are trying to connect to a SharePoint document library (https://foobar.sharepoint.com/_layouts/15/start.aspx#/Shared%20Documents). Try to connect to "https://foobar.sharepoint.com/".
Also the client context might not have enough permissions to perform the search.
Creating a C# application to view folders and files that are stored in AWS S3 for clients that sign up to my site.
Currently I can create a IAM user and assign it permission to a specific folder. But ran into issues when I am trying to view the folder and its contents. I can view the folder if I use the AWS access key and secret key but was wondering if there is a user level credential that I can use to retrieve the folders the user has been given permission to?
This is what I have got so far.
Policy pl = GeneratePolicy(bucketName, foldername);
Credentials creds = GetFederatedCredentials(pl, username);
var sessionCredentials = new SessionAWSCredentials(creds.AccessKeyId, creds.SecretAccessKey, creds.SessionToken);
using (var client = new AmazonS3Client(sessionCredentials, Amazon.RegionEndpoint.USEast1))
{
var response = client.ListObjects(request);
foreach (var subFolder in response.CommonPrefixes)
{
/* list the sub-folders */
Console.WriteLine(subFolder);
}
foreach (var file in response.S3Objects)
{
/* list the files */
}
}
But getting an error on client.ListObjects(request) - access denied error
Here is the GeneratePolicy code
public static Policy GeneratePolicy(string bucket, string username)
{
var statement = new Statement(Statement.StatementEffect.Allow);
// Allow access to the sub folder represented by the username in the bucket
statement.Resources.Add(ResourceFactory.NewS3ObjectResource(bucket, username + "/*"));
// Allow Get and Put object requests.
statement.Actions = new List<ActionIdentifier>() { S3ActionIdentifiers.GetObject, S3ActionIdentifiers.PutObject };
// Lock the requests coming from the client machine.
//statement.Conditions.Add(ConditionFactory.NewIpAddressCondition(ipAddress));
var policy = new Policy();
policy.Statements.Add(statement);
return policy;
}
Here is the GetFederatedCredentials code
public static Credentials GetFederatedCredentials(Policy policy, string username)
{
var request = new GetFederationTokenRequest()
{
Name = username,
Policy = policy.ToJson()
};
var stsClient = new AmazonSecurityTokenServiceClient(AWS_ACCESS_KEY, AWS_SECRET_KEY, Amazon.RegionEndpoint.USEast1);
var response = stsClient.GetFederationToken(request);
return response.GetFederationTokenResult.Credentials;
}
Any help would be greatly appreciated. Thanks in advance
You should add "ListBucket" to the statement.Actions
I tried to Create a new list item using client object model. I have created an asp.net application to do the task. It works if I pass the URL of SharePoint server which is installed in my machine.
But if I give my SharePoint online URL it is not working as below code shows. I get "The remote server returned an error: (403) Forbidden. " error.
Any idea?
ClientContext context = new ClientContext("https://xxx.sharepoint.com/SitePages/");
List announcementsList = context.Web.Lists.GetByTitle("Announcements");
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
Microsoft.SharePoint.Client.ListItem newItem = announcementsList.AddItem(itemCreateInfo);
newItem["Title"] = result.City;
newItem["Body"] = result.State;
newItem.Update();
context.ExecuteQuery();
if you are trying to get a Context object from SharePoint Online you have to put in the right Credentials, as for SharePoint Online you should use the SharePointOnlineCredentials Class
A possible Authentication Method can be look like this:
private void AutheticateO365(string url, string password, string userName)
{
Context = new ClientContext(url);
var passWord = new SecureString();
foreach (char c in password.ToCharArray()) passWord.AppendChar(c);
Context.Credentials = new SharePointOnlineCredentials(userName, passWord);
var web = Context.Web;
Context.Load(web);
Context.ExecuteQuery();
}
I would imagine you just have to supply your login credentials and it should work:
clientContext.Credentials = new NetworkCredential("Username", "Password", "Domain");
You'll need to including System.Net:
using System.Net;