Uploading to SharepointOnline subfolder using Powershell - powershell

it seems like I can upload a file to SPO's Site Collection URL but not the subfolder. For example, I can upload to "https://xyz.sharepoint.com/sites/Reporting", but not "https://xyz.sharepoint.com/sites/Reporting/Sales". Here's the working code's relevant bit:
$Username = "me#domain.com"
$Password = "Password"
$SiteCollectionUrl = "https://xyz.sharepoint.com/sites/Reporting"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$DocLibName = "Sales"
$Folder="C:\MySalesFolder"
Function Get-SPOCredentials([string]$UserName,[string]$Password)
{
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
return New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
}
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteCollectionUrl)
$Context.Credentials = Get-SPOCredentials -UserName $UserName -Password $Password
#Retrieve list
$List = $Context.Web.Lists.GetByTitle($DocLibName)
$Context.Load($List)
$Context.ExecuteQuery()
#Upload file
Foreach ($File in (dir $Folder -File))
{
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $File
$Upload = $List.RootFolder.Files.Add($FileCreationInfo)
$Context.Load($Upload)
$Context.ExecuteQuery()
I tried to hardcode "/Sales" subfolder but no luck. Anyone can point me in the right direction?

According to Trying to upload files to subfolder in Sharepoint Online via Powershell You will need to amend the FileCreationURL:
$FileCreationInfo.URL = $List.RootFolder.ServerRelativeUrl + "/" + $FolderName + "/" + $File.Name
I believe you just need to prepend $File.Name with the Folder path to your root directory.
Web.GetFolderByServerRelativeUrl Method:
Alternatively to attempting to Upload via List.RootFolder..., you can use the "GetFolderByServerRelativeUrl" method to get your Target Folder
$List = $Context.Web.Lists.GetByTitle($DocLibName)
$Context.Load($List.RootFolder)
$Context.ExecuteQuery()
$FolderName = "Sales"
$TargetFolder = $Context.Web.GetFolderByServerRelativeUrl($List.RootFolder.ServerRelativeUrl + "/" + $FolderName);
Then for upload you would use
$FileCreationInfo.URL = $File.Name
$UploadFile = $TargetFolder.Files.Add($FileCreationInfo)
$Context.Load($UploadFile)
$Context.ExecuteQuery()

Related

PowerShell Change Download Folder Pathway in Network Share

I have this script that downloads files from a report server and puts those files in a local network share. The script does what it needs to, but the download folder looks like this hitsqlp -> Extracts -> output -> web16p...this is the pathway of where the folder needs to live, but it is replicating that pathway into subfolders so now I have to click on every subfolder to get to the files.
I want the folder 'SSRSFolder' to be a subfolder of \epicsqlt\Extracts\Output\HIT\web16p
Code below, I'm not sure where I went wrong:
set-location -path \\epicsqlt\Extracts\Output\HIT\web16p
$downloadFolder = "\\epicsqlt\Extracts\Output\HIT\web16p"
$ssrsServer = "blahblahblah"
$secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)" -Credential $mycreds
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)" -UseDefaultCredential
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}
Foreach($ssrsItem in $ssrsItems)
{
# Determine extension for Reports and DataSources
if ($ssrsItem.TypeName -eq "Report")
{
$extension = ".rdl"
}
else
{
$extension = ".rds"
}
Write-Host "Downloading $($ssrsItem.Path)$($extension)";
$downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim()
New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null
$ssrsFile = New-Object System.Xml.XmlDocument
[byte[]] $ssrsDefinition = $null
$ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)
[System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(#(,$ssrsDefinition))
$ssrsFile.Load($memoryStream)
$fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name + $extension;
$ssrsFile.Save($fullDataSourceFileName);
}
if i'm reading this right.
you are starting the script with
set-location -path \epicsqlt\Extracts\Output\HIT\web16p
then you are setting the $downloadfolder variable to that path and including $downloadfolder in your $downloadfoldersub creation.
so the result would be
epicsqlt\Extracts\Output\HIT\web16p\somepath\somefolder\
and then you are creating a new-item with that whole path, when you are already working in the \web16p\ folder.

Invalid Characters in Add-PnPFile stream output

I am trying to take a string and write it to a new file (or update an existing file) in SharePoint Online. Using the following code, the file is created, but it is full of invalid characters (? inside a diamond) and the string "test string" does not appear.
$RootPath = '/Shared Documents/General'
$FolderName = 'Customer'
$FileName = 'test.txt'
$fileContent = 'test string'
$Size = 8192;
[System.IO.MemoryMappedFiles.MemoryMappedFile]$MMF = [System.IO.MemoryMappedFiles.MemoryMappedFile]::CreateNew($FileName, $Size);
If ($Null -eq $MMF) {
Return;
}
$Stream = $MMF.CreateViewStream();
$StreamWriter = [System.IO.StreamWriter]::new($Stream);
$StreamWriter.Write($FileContent);
Add-PnPFile -FileName $FileName -Folder "$RootPath/$FolderName" -Stream $Stream
$StreamWriter.Dispose();
$Stream.Dispose();
$MMF.Dispose();
Am I encoding the string incorrectly or what?
Sample script for your reference.
#region Variables
$Username = "user#xxx.onmicrosoft.com"
$Password = "Password"
$siteURL = "https://xxx.sharepoint.com/sites/lee"
#endregion Variables
#region Credentials
[SecureString]$SecurePass = ConvertTo-SecureString $Password -AsPlainText -Force
[System.Management.Automation.PSCredential]$PSCredentials = New-Object System.Management.Automation.PSCredential($Username, $SecurePass)
#endregion Credentials
Connect-PnPOnline -Url $siteURL -Credentials $PSCredentials
$RootPath = '/Shared Documents/General'
$FolderName = 'Customer'
$FileName = 'test.txt'
$fileContent = 'test string'
$Stream = [IO.MemoryStream]::new([Text.Encoding]::UTF8.GetBytes($fileContent))
# $Size = 8192;
# [System.IO.MemoryMappedFiles.MemoryMappedFile]$MMF = [System.IO.MemoryMappedFiles.MemoryMappedFile]::CreateNew($FileName, $Size);
# If ($Null -eq $MMF) {
# Return;
# }
# $Stream = $MMF.CreateViewStream();
# $StreamWriter = [System.IO.StreamWriter]::new($Stream);
# $StreamWriter.Write($FileContent);
Add-PnPFile -FileName $FileName -Folder "$RootPath/$FolderName" -Stream $Stream
# $StreamWriter.Dispose();
# $Stream.Dispose();
# $MMF.Dispose();
Write-Host "----"

PowerShell code to send files in each sub-folder as email attachments

I'm trying to write a PowerShell script that would email as attachments, all files in each subfolder of C:\Reports\ together. For instance, if the subfolders are C:\Reports\ABC having a.txt, b.xml and c.jpg and C:\Reports\DEF having d.txt, e.xml and f.pdf, the code should email a.txt, b.xml and c.jpg in one email and d.txt, e.xml and f.pdf in another.
#Connection Details
$username = ”vallabhherlekar#gmail.com”
$password = ”Appya1979!”
$smtpServer = “smtp.gmail.com”
$Directory = Get-ChildItem “C:\Reports\” -Directory
foreach ($d in $Directory) {
$msg = New-Object Net.Mail.MailMessage
$smtp = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
#Uncomment Next line for SSL
$smtp.EnableSsl = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential ($username, $password)
$msg.From = "vallabhherlekar#gmail.com"
$msg.To.Add(“vallabhherlekar#gmail.com”)
$msg.Body=”Please See Attached Files”
$msg.Subject = “Email with Multiple Attachments”
Write-Host "Working on directory $($d.FullName)..."
$files = Get-ChildItem -Path "$($d.FullName)" -File
foreach ($file in $files) {
Write-Host “Attaching File :- ” $file.FullName
$attachment = New-Object System.Net.Mail.Attachment –ArgumentList
$file.FullName
$msg.Attachments.Add($attachment)
}
$smtp.Send($msg)
$attachment.Dispose();
$msg.Dispose();
}

Delete files on FTP site using Webclient and powershell

I found this code on Stackoverflow to get files from an FTP site using Powershell.
It works great, then only thing I want to do is delete the files from the FPT site after I download them.
Is there an easy modification to this script to do that?
Thanks
#FTP Server Information - SET VARIABLES
$ftp = "ftp://XXX.com/"
$user = 'UserName'
$pass = 'Password'
$folder = 'FTP_Folder'
$target = "C:\Folder\Folder1\"
#SET CREDENTIALS
$credentials = new-object System.Net.NetworkCredential($user, $pass)
function Get-FtpDir ($url,$credentials) {
$request = [Net.WebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
if ($credentials) { $request.Credentials = $credentials }
$response = $request.GetResponse()
$reader = New-Object IO.StreamReader $response.GetResponseStream()
$reader.ReadToEnd()
$reader.Close()
$response.Close()
}
#SET FOLDER PATH
$folderPath= $ftp + "/" + $folder + "/"
$Allfiles=Get-FTPDir -url $folderPath -credentials $credentials
$files = ($Allfiles -split "`r`n")
$files
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
$counter = 0
foreach ($file in ($files | where {$_ -like "*.txt"})){
$source=$folderPath + $file
$destination = $target + $file
$webclient.DownloadFile($source, $target+$file)
#PRINT FILE NAME AND COUNTER
$counter++
$counter
$source
}
I created a new function to do the deletes after I get each file
function Del-File($url,$credentials) {
$request2 = [Net.WebRequest]::Create($url)
$request2.Method = [System.Net.WebRequestMethods+FTP]::DeleteFile
if ($credentials) { $request2.Credentials = $credentials }
$response2 = $request2.GetResponse()
}
Here's a hint. Your Method is [System.Net.WebRequestMethods+FTP]::ListDirectory. See here what other methods are available: https://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp(v=vs.110).aspx

How to get items from a Sharepoint Online list using PowerShell?

I'm writing a PowerShell script that connects to a SharePoint website and I'm trying to get the items on a list. Here's my code:
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$SitePassword = ConvertTo-SecureString $SitePwd -AsPlainText -Force
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($SiteUser,$SitePassword)
$Context.Credentials = $Creds
$web = $Context.Web
$Context.Load($web)
$Context.ExecuteQuery()
$List = $Context.Web.Lists.GetByTitle('Déposes')
$Context.Load($List)
$Context.ExecuteQuery()
But now I'm stuck with this $List Object and I can't find a way through. For now, I just want to display my list's items.
The following example demonstrates how to retrieve list items using the SharePoint CSOM API in PowerShell:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
Function Get-SPOContext([string]$Url,[string]$UserName,[string]$Password)
{
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$context = New-Object Microsoft.SharePoint.Client.ClientContext($Url)
$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
return $context
}
Function Get-ListItems([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $Context.Web.Lists.GetByTitle($listTitle)
$qry = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($qry)
$Context.Load($items)
$Context.ExecuteQuery()
return $items
}
$UserName = "jdoe#contoso.onmicrosoft.com"
$Password = Read-Host -Prompt "Enter the password"
$Url = "https://contoso.sharepoint.com/"
$context = Get-SPOContext -Url $Url -UserName $UserName -Password $Password
$items = Get-ListItems -Context $context -ListTitle "Tasks"
foreach($item in $items)
{
#...
}
$context.Dispose()