Moving files from "anywhere" to sharepoint - c#

I am creating an app that will move files from my C drive, or anywhere else, to a specified sharepoint library. I am able to copy the file to a sharepoint Library but I want it to "move" instead of just "copy" i have read documentation but can't find a good link to showcase what I am doing.
Here is the code in my console app that I am trying to accomplish this task
namespace FMB_Reports_Console
{
class Program
{
static void Main(string[] args)
{
using (var db = new FMBDBSTAGEEntities())
{
var dataIterator = db.FMB_Reports_Action.Where(x => x.Active);
foreach (var item in dataIterator)
{
if (item.Active)
{
string filePath = #"C:\Users\fmb03113.FMB\Documents\testing";
string libraryName = item.DropOffPath;
string siteUrl = "https://reports.fmb.com/";
string fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1);
MovingFiles(filePath, libraryName, siteUrl, fileName);
}
}
}
}
public static void MovingFiles(string filePath, string libraryName, string siteUrl, string fileName)
{
using (ClientContext ctx = new ClientContext(siteUrl))
{
FileCreationInformation fcInfo = new FileCreationInformation();
fcInfo.Url = fileName;
fcInfo.Overwrite = true;
fcInfo.Content = System.IO.File.ReadAllBytes(filePath);
//fcInfo.Content = System.IO.File.ReadAllBytes(filePath);
Web myWeb = ctx.Web;
List myLibrary = myWeb.Lists.GetByTitle(libraryName);
var fileToMOve = myLibrary.RootFolder.Files.Add(fcInfo);
//fileToMOve.MoveTo(libraryName, movce);
//myLibrary.RootFolder.MoveTo(libraryName);
ctx.ExecuteQuery();
}
}
}
}

Related

Is it possible to get a batch of text content through Azure DevOps REST API?

I need to get (not download) the content from 10.000~ manifest files within a project in Azure DevOps, but I don't manage to achieve this. I have found several ways to retrieve the content from one file at a time, but in this context, it is neither an efficient nor sustainable solution. I have managed to retrieve all files of a particular file type by checking if the file path ends with the name of the file, then using the TfvcHttpClientBase.GetItemsBatch method. However, this method does not return the item's content.
Program.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
AzureRest azureRest = new AzureRest();
var tfvcItems = azureRest.GetTfvcItems();
List<TfvcItemDescriptor> itemDescriptorsList = new List<TfvcItemDescriptor>();
foreach(var item in tfvcItems)
{
//Example manifest file .NET
if (item.Path.EndsWith("packages.config"))
{
var itemDescriptor = new TfvcItemDescriptor()
{
Path = item.Path,
RecursionLevel = VersionControlRecursionType.None,
Version = "",
VersionOption = TfvcVersionOption.None,
VersionType = TfvcVersionType.Latest
};
itemDescriptorsList.Add(itemDescriptor);
}
}
TfvcItemDescriptor[] itemDescriptorsArray = itemDescriptorsList.ToArray();
var itemBatch = azureRest.GetTfvcItemsBatch(itemDescriptorsArray);
foreach(var itemList in itemBatch)
{
foreach(var itemListList in itemList)
{
Console.WriteLine("Content: " + itemListList.Content); //empty/null
Console.WriteLine("ContentMetadata: " + itemListList.ContentMetadata); //not empty/null
}
}
AzureRest.cs
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
public class AzureRest
{
const string ORG_URL = "https://org/url/url";
const string PROJECT = "Project";
const string PAT = "PersonalAccessToken";
private string GetTokenConfig()
{
return PAT;
}
private string GetProjectNameConfig()
{
return PROJECT;
}
private VssConnection Authenticate()
{
string token = GetTokenConfig();
string projectName = GetProjectNameConfig();
var credentials = new VssBasicCredential(string.Empty, token);
var connection = new VssConnection(new Uri(ORG_URL), credentials);
return connection;
}
public List<TfvcItem> GetTfvcItems()
{
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsAsync(scopePath: "/Path", recursionLevel: VersionControlRecursionType.Full, true).Result;
return tfvcItems;
}
}
public List<List<TfvcItem>> GetTfvcItemsBatch(TfvcItemDescriptor[] itemDescriptors)
{
TfvcItemRequestData requestData = new TfvcItemRequestData()
{
IncludeContentMetadata = true,
IncludeLinks = true,
ItemDescriptors = itemDescriptors
};
var connection = Authenticate();
using (TfvcHttpClient tfvcClient = connection.GetClient<TfvcHttpClient>())
{
var tfvcItems = tfvcClient.GetItemsBatchAsync(requestData).Result;
return tfvcItems;
}
}
}
}
For reference:
I have tested the codes you shared and when debugging at "itemDescriptorsList" and have found that there is no content specified in it, so that's why you cannot get the txt content.
You should first check and add the content property into the "itemDescriptorsList".

Is there a way to get all the subfolder name from a folder of container from azure blob?

I want to fetch all virtual directory name from red circle of image
Update:
using Azure.Storage.Blobs;
using System;
using System.Collections.Generic;
namespace ConsoleApp43
{
class Program
{
static void Main(string[] args)
{
string connectionString = "DefaultEndpointsProtocol=https;AccountName=1123bowman;AccountKey=xxxxxx;EndpointSuffix=core.windows.net";
string folder_main = "test1";
List<string> subs3 = new List<string>();
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
string containerName = "test";
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
var blobs = containerClient.GetBlobs(prefix:folder_main);
foreach (var blob in blobs) {
//Console.WriteLine(blob.Name);
string[] sub_names = blob.Name.Split('/');
if (sub_names.Length>2&&!subs3.Contains(sub_names[1]))
{
subs3.Add(sub_names[1]);
}
}
foreach (var sub3 in subs3)
{
Console.WriteLine(sub3);
}
}
}
}
Original Answer:
Azure Blob storage don't have folder, They are virtual directories.
For your requirement, you can parse the file name based on the code to get the 'folder' you mentioned.

Bulk files upload to ADLS gen 1

Is there anyway to upload or transform multiple files to adls in one attempt(Bulk Upload). If that is not possible any parallel processing feature available??.
Am looking for c# example.
Please advise..
If you want to upload multiple files in one directory, we can use the method BulkUpload to implement bulk upload. Regarding how to use the method, please refer to here
For example
Create a service principal and configure permissions
Code
string TENANT = "";
string CLIENTID = "";
Uri ADL_TOKEN_AUDIENCE = new Uri(#"https://datalake.azure.net/");
string secret_key = "";
var adlServiceSettings = ActiveDirectoryServiceSettings.Azure;
adlServiceSettings.TokenAudience = ADL_TOKEN_AUDIENCE;
var adlCred = await ApplicationTokenProvider.LoginSilentAsync(TENANT, CLIENTID, secret_key, adlServiceSettings);
AdlsClient client = AdlsClient.CreateClient("<>.azuredatalakestore.net", adlCred);
But please note that the method has limits. it just can be used to upload files in the same directory one time and it will upload whole files in the directory. If you want to upload some files in one directory or files in different directories, pleas refer to the following code
static async Task Main(string[] args)
{
string TENANT = "";
string CLIENTID = "";
Uri ADL_TOKEN_AUDIENCE = new Uri(#"https://datalake.azure.net/");
string secret_key = "";
var adlServiceSettings = ActiveDirectoryServiceSettings.Azure;
adlServiceSettings.TokenAudience = ADL_TOKEN_AUDIENCE;
var adlCred = await ApplicationTokenProvider.LoginSilentAsync(TENANT, CLIENTID, secret_key, adlServiceSettings);
AdlsClient client = AdlsClient.CreateClient("<>.azuredatalakestore.net", adlCred);
string[] filePaths = { };
int count = 0;
var tasks = new Queue<Task>();
foreach (string filePath in filePaths)
{
var fileName = "";
// Add the upload task to the queue
tasks.Enqueue(uplaodFile(client, filePath, fileName));
count++;
}
// Run all the tasks asynchronously.
await Task.WhenAll(tasks);
}
private static async Task uplaodFile(AdlsClient client, string filePath, string fileName)
{
using (var createStream = client.CreateFile(fileName, IfExists.Overwrite))
{
using (var fileStrem = File.OpenRead(filePath))
{
await fileStrem.CopyToAsync(createStream);
}
}
}

How to create zip file in memory?

I have to create a zip file from set of urls. and it should have a proper folder structure.
So i tried like
public async Task<byte[]> CreateZip(Guid ownerId)
{
try
{
string startPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "zipFolder");//base folder
if (Directory.Exists(startPath))
{
DeleteAllFiles(startPath);
Directory.Delete(startPath);
}
Directory.CreateDirectory(startPath);
string zipPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{ownerId.ToString()}"); //folder based on ownerid
if (Directory.Exists(zipPath))
{
DeleteAllFiles(zipPath);
Directory.Delete(zipPath);
}
Directory.CreateDirectory(zipPath);
var attachemnts = await ReadByOwnerId(ownerId);
attachemnts.Data.ForEach(i =>
{
var fileLocalPath = $"{startPath}\\{i.Category}";
if (!Directory.Exists(fileLocalPath))
{
Directory.CreateDirectory(fileLocalPath);
}
using (var client = new WebClient())
{
client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
}
});
var zipFilename = $"{zipPath}//result.zip";
if (File.Exists(zipFilename))
{
File.Delete(zipFilename);
}
ZipFile.CreateFromDirectory(startPath, zipFilename, CompressionLevel.Fastest, true);
var result = System.IO.File.ReadAllBytes(zipFilename);
return result;
}
catch (Exception ex)
{
var a = ex;
return null;
}
}
currently im writing all files in my base directory(may be not a good idea).corrently i have to manually delete all folders and files to avoid exception/unwanted files. Can everything be written in memory?
What changes required to write all files and folder structure in memory?
No you can't. Not with the built in Dotnet any way.
As per my comment I would recommend storing the files in a custom location based on a Guid or similar. Eg:
"/xxxx-xxxx-xxxx-xxxx/Folder-To-Zip/....".
This would ensure you could handle multiple requests with the same files or similar file / folder names.
Then you just have to cleanup and delete the folder again afterwards so you don't run out of space.
Hope the below code does the job.
public async Task<byte[]> CreateZip(Guid ownerId)
{
try
{
string startPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}_zipFolder");//folder to add
Directory.CreateDirectory(startPath);
var attachemnts = await ReadByOwnerId(ownerId);
attachemnts.Data = filterDuplicateAttachments(attachemnts.Data);
//filtering youtube urls
attachemnts.Data = attachemnts.Data.Where(i => !i.Flags.Equals("YoutubeUrl", StringComparison.OrdinalIgnoreCase)).ToList();
attachemnts.Data.ForEach(i =>
{
var fileLocalPath = $"{startPath}\\{i.Category}";
if (!Directory.Exists(fileLocalPath))
{
Directory.CreateDirectory(fileLocalPath);
}
using (var client = new WebClient())
{
client.DownloadFile(i.Url, $"{fileLocalPath}//{i.Flags ?? ""}_{i.FileName}");
}
});
using (var ms = new MemoryStream())
{
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
System.IO.DirectoryInfo di = new DirectoryInfo(startPath);
var allFiles = di.GetFiles("",SearchOption.AllDirectories);
foreach (var attachment in allFiles)
{
var file = File.OpenRead(attachment.FullName);
var type = attachemnts.Data.Where(i => $"{ i.Flags ?? ""}_{ i.FileName}".Equals(attachment.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
var entry = zipArchive.CreateEntry($"{type.Category}/{attachment.Name}", CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
file.CopyTo(entryStream);
}
}
}
var result = ms.ToArray();
return result;
}
}
catch (Exception ex)
{
var a = ex;
return null;
}
}

Publish a project programmatically C#

I want to be able to publish a separate C# project programmatically. When I run the following code I want it to publish my Repair.csproj project.
What I'm doing here is I'm getting the version number from my code. I then increment it by one, delete everything in the publish folder and then try to publish my project.
However when I run this code it doesn't publish my Repair.csproj. I'm not sure where I'm going wrong.
My code is as follows
public const string publishLocation = #"C:\Workspace_User\Repair\MAIN\Publish";
public const string RepairLocation = #"C:\Workspace_User\Repair\MAIN\Repair.sln";
public const string repairproj = #"C:\Workspace_User\Repair\MAIN\Repair\Repair.csproj";
public const string r = #"C:\Workspace_User\Repair\MAIN\Repair\bin\Release\Repair.dll";
static void Main(string[] args)
{
Microsoft.Build.BuildEngine.Engine.GlobalEngine.BuildEnabled = true;
System.IO.DirectoryInfo di = new DirectoryInfo(publishLocation);
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(RepairLocation);
var version= AssemblyName.GetAssemblyName(r).Version;
var splitVersionNumber= version.ToString().Split('.');
var getNumber = splitVersionNumber[3];
var addInt=Convert.ToInt32(getNumber);
addInt++;
foreach (FileInfo file in di.GetFiles())
{
if (file.Name!="Working Folder")
{
file.Delete();
}
}
buildMethod();
}
public static object buildMethod()
{
var props = new Dictionary<string, string>();
props["Configuration"] = "Publish";
var request = new BuildRequestData(repairproj, props, null, new string[] { "Build" }, null);
var parms = new BuildParameters();
// parms.Loggers = ...;
var result = BuildManager.DefaultBuildManager.Build(parms, request);
Debug.Write(result);
return result.OverallResult == BuildResultCode.Success;
}

Categories

Resources