Delete files on FTP site using Webclient and powershell - 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

Related

PowerShell script for checking links in SharePoint Pages

I'm trying to check whether every page on a given Sharepoint site contains certain URL with the following PowerShell script. It seems that the foreach loop does nothing at all. Whats should be the reason for this? Also I'm not getting any error messages. I successfully changed some of the list's properties but can't process the data.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
#Mysite URL
$site = 'https://contoso.sharepoint.com/sites/contoso'
$urlToFind = "https://google.com"
#Admin User Principal Name
$admin = 'SampleUsername'
#Get Password as secure String
$Password = "SamplePassword"
$SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
#Get the Client Context and Bind the Site Collection
$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
#Authenticate
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin , $SecurePassword)
$context.Credentials = $credentials
$list = $context.Web.Lists.GetByTitle('Pages')
$context.Load($list)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$Items = $list.GetItems($query)
$context.Load($Items)
$context.ExecuteQuery()
$dataValues = #()
$items.GetEnumerator() | % {
$dataValues += $_.FieldValues
}
$dataValues.Count #determine the amount of items
foreach($item in $dataValues)
{
write-host "inside"
write-host ""
write-host "*** PAGE *** "$item.Url
write-host ""
$file = $item.File
#get binary data, and decode into text
$data = $file.OpenBinary()
$encode = New-Object System.Text.ASCIIEncoding
$text = $encode.GetString($data)
if($text -match $urlToFind)
{
write-warning "FOUND BAD URL IN THIS DOCUMENT!"
}
else {
write-host "nothing found"
}
#comment below to parse all pages
#break
}
We are unable to foreach $list.Items to $item.
We need query $Items by
$Items = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
Then
foreach($item in $Items)

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();
}

Uploading to SharepointOnline subfolder using 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()

Email Value From Variable & Hyperlink

From within PowerShell, I know how to send a basic email. But with my syntax below, how could I append to the body of the email each $QueryName and each $RowCount and add a hyperlink to the value contained in $FPath\$FormattedDate\so the body of email would look like this:
$QueryName - $RowCount
(or with actual data)
Santa - 14
Mickey - 12
Mars - 2
Here is my current PS script
Function Execute-SQLquery {
param ($QueryName, $QueryString)
$server = "Server"
$database = "DB1"
$FPath = "C:\Testing"
#Setting additional variables
$extension = ".csv"
$date = Get-Date -f 'MM.dd.yy'
$FormattedDate = Get-Date -f 'MM.dd.yy'
$connectionTemplate = "Data Source={0};Integrated Security=SSPI;Initial Catalog={1};"
$connectionString = [string]::Format($connectionTemplate, $server, $database)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $QueryString
$command.Connection = $connection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$rowCount = $SqlAdapter.Fill($DataSet)
if(!(Test-Path -path "$FPath\$FormattedDate\")){New-Item "$FPath\$FormattedDate\" -type directory}
if ($rowCount -gt 0)
{
if ($QueryName -eq "Santa")
{
$extractFile = "C:\Testing\TemplateFiles\Santa.csv"
[System.IO.Directory]::CreateDirectory("$FPath\$FormattedDate\Santa\")
Write-Host $rowCount -fore Red
$dirName = "$FPath\$FormattedDate\Santa\"
$filename = [IO.Path]::GetFileNameWithoutExtension($extractFile) + "_$date" + [IO.Path]::GetExtension($extractFile)
$extractFile = Join-Path $dirname $filename
}
if ($QueryName -eq "Mickey")
{
$extractFile = "C:\Testing\TemplateFiles\Mickey.csv"
[System.IO.Directory]::CreateDirectory("$FPath\$FormattedDate\Mickey\")
Write-Host $rowCount -fore Red
$dirName = "$FPath\$FormattedDate\Mickey\"
$filename = [IO.Path]::GetFileNameWithoutExtension($extractFile) + "_$date" + [IO.Path]::GetExtension($extractFile)
$extractFile = Join-Path $dirname $filename
}
if ($QueryName -eq "Mars")
{
$extractFile = "C:\Testing\TemplateFiles\Mickey\Mars.csv"
[System.IO.Directory]::CreateDirectory("$FPath\$FormattedDate\Mars\")
Write-Host $rowCount -fore Red
$dirName = "$FPath\$FormattedDate\Mars\"
$filename = [IO.Path]::GetFileNameWithoutExtension($extractFile) + "_$date" + [IO.Path]::GetExtension($extractFile)
$extractFile = Join-Path $dirname $filename
}
$DataSet.Tables[0] | Export-Csv $extractFile -NoTypeInformation
}
$connection.Close()
}
First up, since the only thing that changes based on $QueryName are direct references to the value in $QueryName and the $extractFile, you'd be better off not repeating that entire block.
For the mail message, you can use Send-MailMessage.
To add a link to a local file resource, use the file:/// scheme prefix and change all backslashes (\) to forward slashes (/), ie. file:///C:/Document/Path.ext, or in your example "file:///$("$FPath\$FormattedDate" -replace '\','/')":
Function Execute-SQLquery {
param ($QueryName, $QueryString)
# up to this point no change is required
if ($rowCount -gt 0)
{
$extractFile = switch($QueryName){
"Santa" { "C:\Testing\TemplateFiles\Santa.csv" }
"Mickey" { "C:\Testing\TemplateFiles\Mickey.csv" }
"Mars" { "C:\Testing\TemplateFiles\Mars\Mickey.csv" }
default { throw "Illegal QueryName" }
}
[System.IO.Directory]::CreateDirectory("$FPath\$FormattedDate\$QueryName\")
Write-Host $rowCount -fore Red
$dirName = "$FPath\$FormattedDate\$QueryName\"
$filename = [IO.Path]::GetFileNameWithoutExtension($extractFile) + "_$date" + [IO.Path]::GetExtension($extractFile)
$extractFile = Join-Path $dirname $filename
$DataSet.Tables[0] | Export-Csv $extractFile -NoTypeInformation
$EmailBody = #'
Here are the results:
{0} - {1}
Find the documents here
'# -f $QueryName,$rowCount,$("$FPath\$FormattedDate" -replace '\','/')
Send-MailMessage -From "me#company.example" -To "you#company.example" -Body $EmailBody -BodyAsHtml:$true -Subject "Data extracted!" -SmtpServer "your.mail.server.company.example"
}
$connection.Close()
}