C# - CSOM - Upload a file to a subdirectory in Sharepoint Online - c#

I'm trying to upload a file to SharePoint Online and I got this sample code:
var uploadFile = list
.RootFolder
.Folders
.GetByPath(ResourcePath.FromDecodedUrl("A"))
.Files
.Add(newFile);
ctx.Load(uploadFile);
await ctx.ExecuteQueryAsync();
Which works perfectly fine, so everything around it works. But apparently this snippet
var uploadFile = list
.RootFolder
.Folders
.GetByPath(ResourcePath.FromDecodedUrl("A/B"))
.Files
.Add(newFile);
ctx.Load(uploadFile);
await ctx.ExecuteQueryAsync();
Throws System.IO.DirectoryNotFoundException even though both directories exist. So how can I upload a file to the subdirectory "B"?

Try to upload file like this:
public static void UploadFile(ClientContext context,string uploadFolderUrl, string uploadFilePath)
{
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.GetFileName(uploadFilePath)
};
var targetFolder = context.Web.GetFolderByServerRelativeUrl(uploadFolderUrl);
var uploadFile = targetFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
}
using (var ctx = new ClientContext(webUri))
{
ctx.Credentials = credentials;
UploadFile(ctx,"LibName/FolderName/Sub Folder Name/Sub Sub Folder Name/Sub Sub Sub Folder Name",filePath);
}
Please check out another similiar thread here:
Alternative Save/OpenBinaryDirect methods for CSOM for SharePoint Online

Related

Downloading images from publicly shared folders and sub-folders on Dropbox

This is similar to my previous question:
Downloading images from publicly shared folder on Dropbox
I have this piece of code (simplified version) that needs to download all images from publicly shared folder and all sub-folders.
using Dropbox.Api;
using Dropbox.Api.Files;
...
// AccessToken - get it from app console
// FolderToDownload - https://www.dropbox.com/sh/{unicorn_string}?dl=0
using (var dbx = new DropboxClient(_dropboxSettings.AccessToken))
{
var sharedLink = new SharedLink(_dropboxSettings.FolderToDownload);
var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink);
// var sharedFiles = await dbx.Files.ListFolderAsync(path: "", sharedLink: sharedLink, recursive: true);
// "recursive: true" throws: Error in call to API function "files/list_folder": Recursive list folder is not supported for shared link.
foreach (var entry in sharedFiles.Entries)
{
if (entry.IsFile)
{
var link = await dbx.Sharing.GetSharedLinkFileAsync(url: _dropboxSettings.FolderToDownload, path: "/" + entry.Name);
var byteArray = await link.GetContentAsByteArrayAsync();
}
if (entry.IsFolder)
{
var subFolder = entry.AsFolder;
// var folderContent = await dbx.Files.ListFolderAsync(path: subFolder.Id);
// var subFolderSharedLink = new SharedLink(???);
}
}
}
How do I list entries of all sub-folders?
For any given subfolder, to list its contents, you'll need to call back to ListFolderAsync again, using the same sharedLink value, but supplying a path value for the subfolder, relative to the root folder for the shared link.
For example, if you list the contents of the folder shared link, and one of the entries is a folder with the name "SomeFolder", to then list the contents of "SomeFolder", you would need to make a call like:
await dbx.Files.ListFolderAsync(path: "/SomeFolder", sharedLink: sharedLink);

Open Local HTML files in Xamarin.Forms Web View NOT in Assets Folder

I am trying to open a multipage HTML web page (i.e. test.html, test.css and test.js) which has been downloaded dynamically (thefore can't use assets) and stored in the apps internal storage (Xamarin.Essentials.FileSystem.AppDataDirectory).
The URL I am trying to use is as follows:
file:///data/user/0/com.test/files/HTML/Test.html
However I just get file not found.
var filesToDownload = new string[] { "http://myserver/test/test.html", "http://myserver/test/test.css" };
var directory = System.IO.Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "HTML");
if (System.IO.Directory.Exists(directory))
{
System.IO.Directory.Delete(directory, true);
}
System.IO.Directory.CreateDirectory(directory);
using (var wc = new System.Net.WebClient())
{
foreach (var f in filesToDownload)
{
wc.DownloadFile(f, System.IO.Path.Combine(directory, System.IO.Path.GetFileName(f)));
}
}
var source = new UrlWebViewSource
{
Url = System.IO.Path.Combine("file://" + directory, "Test.html")
};
WebView1.Source = source;
There are several points you have to make sure:
1 Add the Xamarin.Essentials NuGet package to each project
2 http://myserver/test/test.html and http://myserver/test/test.css are existed and accessible.
3 The file name of webview source should be the same with the file name you have written to your storage. Not Test.html, but test.html
So
Url = System.IO.Path.Combine("file://" + directory, "Test.html") should be modified to
Url = System.IO.Path.Combine("file://" + directory, "test.html")

Programatically target default document library for file upload in SP16

I made a C# application for uploading files to SharePoint. So far it Works as intended, on all document libraries except the default one. Everytime it throws an exception : List 'Documents' does not exist at site with URL 'http://...'
I've tried with "Shared Documents" as well, but same result. Does the default library have some internal name I'm not aware of?
The code for uploading is as follows:
// Get the SharePoint context
ClientContext context = new ClientContext(domain);
// Open the web
var web = context.Web;
String[] files = System.IO.File.ReadAllLines(args[0]);
foreach (String file in files)
{
// Create the new file
var newFile = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(file),
Url = Path.GetFileName(file),
Overwrite = true
};
// Get a reference to the document library
var docs = web.Lists.GetByTitle(library);
var uploadFile = docs.RootFolder.Files.Add(newFile);
// Upload the document
context.Load(uploadFile);
}
First of all, it is much safer to get list by url, not title.
using (ClientContext context = new ClientContext("https://sharepoint.domain.com"))
{
context.Load(context.Web, w => w.ServerRelativeUrl);
context.ExecuteQuery();
List list = context.Web.GetList($"{context.Web.ServerRelativeUrl.TrimEnd('/')}/Shared Documents");
}
Also don't forget to dispose the object context.
Check enabled alternate languages (Site settings > Site Administration > Language settings). You may have more enabled languages and the default one could be different then you expect. Each language holds its own list name.

How to upload a file in a Sharepoint library subfolder using c#?

I need to upload a file using c# console app in a sharepoint library. I manage to upload it to the parent library only. But the requirement is to upload it on its sub folder.
So here's the Folder Structure:
Root Folder
-Sub Folder 1
---Sub Folder 2
----Sub Folder 3
I need to upload it in Sub Folder 3. Right now, I'm only able to upload on the Root Folder.
It throws an error when I tried to input the Sub Folder 3 in the GetByTitle method, but when it's the root folder, it is succeeding to upload.
Here's my code.
using (ClientContext clientContext = new ClientContext(siteURL))
{
clientContext.Credentials = new System.Net.NetworkCredential(#"username", "password", "domain");
var web = clientContext.Web;
// Create the new file
var newFile = new FileCreationInformation();
newFile.Content = System.IO.File.ReadAllBytes(#"C:\filepath\test.xlsx");
newFile.Overwrite = true;
newFile.Url = "Test Upload.xlsx";
List list = web.Lists.GetByTitle("Service Oriented Architecture (SOA)");
clientContext.Load(list);
clientContext.ExecuteQuery();
clientContext.Load(list.RootFolder);
clientContext.Load(list.RootFolder.Folders);
clientContext.ExecuteQuery();
foreach (Folder SubFolder in list.RootFolder.Folders)
{
if (SubFolder.Name.Equals("07 - SOA Environment"))
{
//What's next?
}
}
}
There are several options how to specify sub folder while uploading the file using CSOM
There are two assumptions about the provided solutions below:
The library name(url) is Documents and has the following folder structure:
Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder/
Folder structure already exists
Using FileCreationInformation.Url property
Use FileCreationInformation.Url property to specify the folder url for a uploaded file.
The following example demonstrates how to specify relative url (a slightly modified version of your example, the main difference comes in specifying FileCreationInformation.Url)
var uploadFilePath = #"c:\tmp\SharePoint User Guide.docx";
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.Combine("Documents/Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder/", Path.GetFileName(uploadFilePath))
};
var list = context.Web.Lists.GetByTitle("Root Folder");
var uploadFile = list.RootFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
Using Web.GetFolderByServerRelativeUrl method
Use Web.GetFolderByServerRelativeUrl method to retrieve a folder where file have to be uploaded:
public static void UploadFile(ClientContext context,string uploadFolderUrl, string uploadFilePath)
{
var fileCreationInfo = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(uploadFilePath),
Overwrite = true,
Url = Path.GetFileName(uploadFilePath)
};
var targetFolder = context.Web.GetFolderByServerRelativeUrl(uploadFolderUrl);
var uploadFile = targetFolder.Files.Add(fileCreationInfo);
context.Load(uploadFile);
context.ExecuteQuery();
}
Usage
using (var ctx = new ClientContext(webUri))
{
ctx.Credentials = credentials;
UploadFile(ctx,"Documents/Folder/Sub Folder/Sub Sub Folder/Sub Sub Sub Folder",filePath);
}
You need to get sub folder within folder. like below
docs.RootFolder.SubFolders
Remaining things is same, just need to add in same folder.
try to go into folder like below
docs.Folders["FolderName"]

Copying/over-writing one source to another in TFS?

Question Background:
Within my TF Server I have two folders, one is a simple 'HelloWorld.sln' in a folder called 'HelloWorldDev' and the other is a 'HelloWorld.sln' in a folder called 'HelloWorldQA'. Each folder contains its respective .cs files etc.
I want to checkout a file from the HelloWorld QA folder, replace - or update it - with a version from the HelloWorldDev folder with the same file name, then check this file back into the HelloWorldQA folder with the relevant changes.
Question:
I am very new to the TFS API so I'm not 100% if what I'm trying to ask is the correct way to proceed, or if its even possible. Can someone give me an example of achieving this?
Code so far:
string fileName = #"C:\Users\Me\Documents\TfsServer\HelloWorldQA\IHelloWorld.cs";
string fileNameQA = #"C:\Users\Me\Documents\TfsServer\HelloWorld\IHelloWorld.cs";
string uri = #"https://tfsServer.visualstudio.com/";
var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(fileName);
var server = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspace = workspaceInfo.GetWorkspace(server);
workspace.PendEdit(fileName);
FileInfo fi = new FileInfo(fileName);
var workspaceInfoQA = Workstation.Current.GetLocalWorkspaceInfo(fileNameQA);
var serverQA = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspaceQA = workspaceInfo.GetWorkspace(serverQA);
workspace.PendEdit(fileNameQA);
FileInfo fiQA = new FileInfo(fileNameQA);
First, instead of using 2 workspaces, you can simply map both folders in the same workspace.
Then you're looking for a merge operation:
var sourcePath = workspace.GetServerItemForLocalItem(fileName);
var targetPath = workspace.GetServerItemForLocalItem(fileNameQA);
var getStatus = workspace.Merge(sourcePath, targetPath, null, null);
if (getStatus.NumUpdated > 0)
{
//OK
}

Categories