Olá pessoal,
Boa tarde!
Neste post, vou falar novamente sobre o CLR (C#), demonstrando mais uma utilidade desse poderoso recurso do SQL Server, que é a integração entre o banco de dados e servidores FTP, seja para baixar (download) ou subir (upload) arquivos entre uma pasta local ou da sua rede e o servidor FTP.
Esse recurso é especialmente útil quando você precisar integrações com outras empresas, onde você precisa exportar dados e disponibilizá-los em um FTP externo de outra empresa ou importar arquivos de um FTP e importar para a sua rede ou para o seu banco de dados.
Para retornar mensagens de alerta e mensagens de erro do CLR para o banco de dados, utilizo a classe Retorno, que está disponível no post SQL Server – Como enviar avisos e mensagens de erro para o banco pelo CLR (C#) e é uma dependência dessa classe de FTP.
Em todas as rotinas, coloquei um “retry” de até 10 tentativas em casos de falha de conexão ou timeout, de forma que a sua rotina não apresente falha por alguma instabilidade da rede (isso já me ajudou MUITO).
Caso você não conheça o CLR ou não saiba por onde começar, veja mais acessando o post Introdução ao SQL CLR (Common Language Runtime) no SQL Server.
Classe Base – FTPControle.cs
Visualizar mais detalhes, exemplos de uso e código-fonteApesar do código ser bem grande, ela não é uma classe complexa, e pode ser facilmente compreendida.
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Globalization;
using System.Net;
using System.IO;
namespace Bibliotecas.Model
{
public class FTPControle
{
public string Host { get; set; }
public string Login { get; set; }
public string Senha { get; set; }
private FtpWebRequest _ftp;
public FTPControle(string host, string login, string senha)
{
Host = host;
Login = login;
Senha = senha;
}
public void ApagarArquivos(string pastaFtp, List<string> arquivos)
{
foreach (var arquivo in arquivos)
{
var arquivoFtp = Host + pastaFtp + arquivo;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.DeleteFile;
_ftp.GetResponse();
}
}
public void ApagarArquivo(string pastaFtp, string arquivo)
{
var arquivoFtp = Host + pastaFtp + arquivo;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.DeleteFile;
_ftp.GetResponse();
}
public List<string> ListarArquivos(string pastaFtp, string filtro)
{
var _pastaFtp = Host + pastaFtp;
_ftp = (FtpWebRequest)WebRequest.Create(_pastaFtp);
var arquivos = new List<string>();
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.ListDirectory;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (var r = new StreamReader(responseStream))
{
var s = r.ReadLine();
while (s != null)
{
arquivos.Add(s);
s = r.ReadLine();
}
}
}
}
}
return arquivos.FindAll(
nome => nome.Contains(filtro.Replace("*", ""))
);
}
public List<string> ListarArquivosCompleto(string pastaFtp, string filtro)
{
var _pastaFtp = Host + pastaFtp;
_ftp = (FtpWebRequest) WebRequest.Create(_pastaFtp);
var arquivos = new List<string>();
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (var r = new StreamReader(responseStream))
{
var s = r.ReadLine();
while (s != null)
{
arquivos.Add(s);
s = r.ReadLine();
}
}
}
}
}
return arquivos.FindAll(
nome => nome.Contains(filtro.Replace("*", ""))
);
}
private static string GetOctalPermission(string Ds_Permissao)
{
switch (Ds_Permissao)
{
case "---":
return "0";
case "--x":
return "1";
case "-w-":
return "2";
case "-wx":
return "3";
case "r--":
return "4";
case "r-x":
return "5";
case "rw-":
return "6";
case "rwx":
return "7";
default:
return "";
}
}
private static int GetMonth(string Ds_Mes)
{
switch (Ds_Mes.ToLower())
{
case "jan":
return 1;
case "feb":
return 2;
case "mar":
return 3;
case "apr":
return 4;
case "may":
return 5;
case "jun":
return 6;
case "jul":
return 7;
case "aug":
return 8;
case "sep":
return 9;
case "oct":
return 10;
case "nov":
return 11;
case "dec":
return 12;
default:
return 0;
}
}
private static string GetMonthName(string Ds_Mes)
{
switch (Ds_Mes)
{
case "1":
return "jan";
case "2":
return "feb";
case "3":
return "mar";
case "4":
return "apr";
case "5":
return "may";
case "6":
return "jun";
case "7":
return "jul";
case "8":
return "aug";
case "9":
return "sep";
case "10":
return "oct";
case "11":
return "nov";
case "12":
return "dez";
default:
return "";
}
}
public FTPArquivoListar ListarArquivosCompleto_Parse(string arquivo, string Ds_Pasta_FTP, int Nr_Contador)
{
try
{
var dir = (arquivo.Substring(0, 1) == "d") ? "d" : "f";
var owner = "";
var group = "";
var ownerSec = "";
var groupSec = "";
var everyoneSec = "";
var size = 0;
var month = "";
var year = "";
var day = "";
var filename = "";
SqlDateTime data;
if (arquivo.Substring(15, 2).ToUpper() == "AM" || arquivo.Substring(15, 2).ToUpper() == "PM")
{
dir = arquivo.Contains("<DIR>") ? "d" : "f";
int.TryParse(arquivo.Substring(29, 9).Trim(), out size);
month = arquivo.Substring(0, 2);
day = arquivo.Substring(3, 2);
year = arquivo.Substring(6, 2);
year = (int.Parse(year) > DateTime.Now.Year ? "19" : "20") + year;
var hora = int.Parse(arquivo.Substring(10, 2)) + (arquivo.Substring(15, 2).ToUpper() == "PM" && int.Parse(arquivo.Substring(10, 2)) < 12 ? 12 : 0);
var minuto = int.Parse(arquivo.Substring(13, 2));
data = new DateTime(int.Parse(year), int.Parse(month), int.Parse(day), hora, minuto, 0);
filename = arquivo.Substring(39, arquivo.Length - 39).Trim();
}
else
{
var palavras = arquivo.Split(' ');
var contador = 1;
ownerSec = arquivo.Substring(1, 3).Trim();
groupSec = arquivo.Substring(4, 3).Trim();
everyoneSec = arquivo.Substring(7, 3).Trim();
foreach (var palavra in palavras)
{
if (contador == 3)
{
owner = palavra.Trim();
}
else if (contador == 4)
{
group = palavra.Trim();
}
else if (contador == 5)
{
int.TryParse(palavra.Trim(), out size);
}
else if (contador == 6)
{
month = palavra.ToLower().Trim();
}
else if (contador == 7)
{
day = palavra.Trim();
}
else if (contador == 8)
{
year = palavra.Trim();
}
else
{
if (contador >= 9)
{
filename += palavra;
}
}
if (!string.IsNullOrEmpty(palavra) || contador >= 9)
contador++;
}
if (year.IndexOf(":", StringComparison.Ordinal) >= 0)
{
var mes = GetMonth(month);
var time = year.Split(':');
data = mes > DateTime.Now.Month ? new SqlDateTime(DateTime.Now.Year - 1, mes, Convert.ToInt32(day), Convert.ToInt32(time[0]), Convert.ToInt32(time[1]), 0) : new SqlDateTime(DateTime.Now.Year, mes, Convert.ToInt32(day), Convert.ToInt32(time[0]), Convert.ToInt32(time[1]), 0);
}
else
{
var dataOrigem = DateTime.ParseExact(year + "-" + month + "-" + day, "yyyy-MMM-d", new CultureInfo("en-US"));
data = Convert.ToDateTime(dataOrigem.ToString("dd/MM/yyyy", new CultureInfo("pt-BR")));
}
}
if (filename == "." || filename == "..")
{
return new FTPArquivoListar(
0,
"Diretorio",
Ds_Pasta_FTP + "/",
filename, //arquivo,
size,
SqlDateTime.Null,
ownerSec + groupSec + everyoneSec,
"0" + GetOctalPermission(ownerSec) + GetOctalPermission(groupSec) + GetOctalPermission(everyoneSec),
owner,
group
);
}
return new FTPArquivoListar(
Nr_Contador,
(dir == "d" ? "Diretorio" : "Arquivo"),
Ds_Pasta_FTP + "/",
filename, //arquivo,
size,
data,
ownerSec + groupSec + everyoneSec,
"0" + GetOctalPermission(ownerSec) + GetOctalPermission(groupSec) + GetOctalPermission(everyoneSec),
owner,
group
);
}
catch (Exception e)
{
return new FTPArquivoListar(
0,
"Erro",
arquivo,
e.Message, //arquivo,
0,
SqlDateTime.Null,
"",
"000",
"",
""
);
}
}
public int BaixarArquivos(string pastaFtp, List<string> arquivos, string pastaLocal)
{
var buffer = new byte[2048];
foreach (var arquivo in arquivos)
{
var arquivoFtp = Host + pastaFtp + arquivo;
var arquivoLocal = pastaLocal + arquivo;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.DownloadFile;
using (var response = (FtpWebResponse)_ftp.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var fs = new FileStream(arquivoLocal, FileMode.Create))
{
if (responseStream != null)
{
var read = responseStream.Read(buffer, 0, buffer.Length); ;
while (read != 0)
{
fs.Write(buffer, 0, read);
read = responseStream.Read(buffer, 0, buffer.Length);
}
}
fs.Flush();
}
}
}
}
return arquivos.Count;
}
public void BaixarArquivo(string pastaFtp, string arquivo, string arquivoLocal)
{
var buffer = new byte[2048];
var arquivoFtp = Host + pastaFtp + arquivo;
var _arquivoLocal = arquivoLocal;
_ftp = (FtpWebRequest) WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.DownloadFile;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
using (var fs = new FileStream(_arquivoLocal, FileMode.Create))
{
if (responseStream != null)
{
var read = responseStream.Read(buffer, 0, buffer.Length); ;
while (read != 0)
{
fs.Write(buffer, 0, read);
read = responseStream.Read(buffer, 0, buffer.Length);
}
}
fs.Flush();
}
}
}
}
public int SubirArquivos(List<string> arquivos, string pastaFtp)
{
foreach (var arquivo in arquivos)
{
string nomeArquivo;
if (arquivo.LastIndexOf(@"/", StringComparison.Ordinal) > 0)
nomeArquivo = arquivo.Substring(arquivo.LastIndexOf(@"/", StringComparison.Ordinal),arquivo.Length - arquivo.LastIndexOf(@"/", StringComparison.Ordinal));
else
if (arquivo.LastIndexOf(@"\", StringComparison.Ordinal) > 0)
nomeArquivo = arquivo.Substring(arquivo.LastIndexOf(@"\", StringComparison.Ordinal), arquivo.Length - arquivo.LastIndexOf(@"\", StringComparison.Ordinal));
else
return -1;
var arquivoFtp = Host + pastaFtp + nomeArquivo;
var arquivoLocal = arquivo;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.UploadFile;
_ftp.Timeout = 600000;
byte[] buffer;
using (var stream = File.OpenRead(arquivoLocal))
{
buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
}
using (var reqStream = _ftp.GetRequestStream())
{
reqStream.Write(buffer, 0, buffer.Length);
}
}
return arquivos.Count;
}
public void SubirArquivo(string arquivoLocal, string pastaFtp, string nomeArquivoRemoto)
{
var arquivoFtp = Host + pastaFtp + nomeArquivoRemoto;
var _arquivoLocal = arquivoLocal;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.UploadFile;
_ftp.Timeout = 600000;
byte[] buffer;
using (var stream = File.OpenRead(_arquivoLocal))
{
buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
}
using (var reqStream = _ftp.GetRequestStream())
{
reqStream.Write(buffer, 0, buffer.Length);
}
}
public FtpWebResponse CriaDiretorio(string pastaFtp)
{
var arquivoFtp = Host + "/" + pastaFtp;
_ftp = (FtpWebRequest) WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.MakeDirectory;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
return response;
}
}
public FtpWebResponse ApagaArquivo(string pastaFtp, string arquivoRemoto)
{
var arquivoFtp = Host + "/" + pastaFtp + "/" + arquivoRemoto;
_ftp = (FtpWebRequest) WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.DeleteFile;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
return response;
}
}
public FtpWebResponse ApagaDiretorio(string pastaFtp, bool apagaArquivos)
{
pastaFtp = ("/" + pastaFtp + "/").Replace("//", "/");
if (apagaArquivos)
{
var filesList = ListarArquivos(pastaFtp, "*.*");
foreach (var file in filesList)
{
ApagaArquivo(pastaFtp, file);
}
}
var arquivoFtp = Host + pastaFtp;
_ftp = (FtpWebRequest)WebRequest.Create(arquivoFtp);
IniciarMetodo();
_ftp.Method = WebRequestMethods.Ftp.RemoveDirectory;
using (var response = (FtpWebResponse) _ftp.GetResponse())
{
return response;
}
}
private void IniciarMetodo()
{
//_ftp.Proxy = new WebProxy(Servidor.Ds_Proxy_Url, Servidor.Ds_Proxy_Porta) { Credentials = new NetworkCredential(Servidor.Ds_Proxy_Usuario, Servidor.Ds_Proxy_Senha, Servidor.Ds_Proxy_Dominio) };
_ftp.Proxy = null;
_ftp.Credentials = new NetworkCredential(Login, Senha);
_ftp.KeepAlive = false;
_ftp.UseBinary = true;
_ftp.UsePassive = true;
}
}
public class FTPArquivoListar
{
public SqlInt32 Nr_Linha;
public SqlString Nm_Arquivo;
public SqlString Nm_Diretorio;
public SqlString Fl_Tipo;
public SqlInt64 Qt_Tamanho;
public SqlDateTime Dt_Criacao;
public SqlString Ds_Permissao;
public SqlString Ds_Permissao_Octal;
public SqlString Ds_Proprietario;
public SqlString Ds_Grupo;
public FTPArquivoListar(SqlInt32 nrLinha, SqlString nmArquivo, SqlString nmDiretorio, SqlString flTipo, SqlInt64 qtTamanho, SqlDateTime dtCriacao, SqlString dsPermissao, SqlString dsPermissaoOctal, SqlString dsProprietario, SqlString dsGrupo)
{
Nr_Linha = nrLinha;
Nm_Arquivo = nmArquivo;
Nm_Diretorio = nmDiretorio;
Fl_Tipo = flTipo;
Qt_Tamanho = qtTamanho;
Dt_Criacao = dtCriacao;
Ds_Permissao = dsPermissao;
Ds_Permissao_Octal = dsPermissaoOctal;
Ds_Proprietario = dsProprietario;
Ds_Grupo = dsGrupo;
}
}
}
Como listar arquivos de um FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteO parâmetro filtro permite informar o nome do arquivo que se desejar filtrar ou utilizar um Wildcard para retornar apenas os arquivos que atendam ao critério informado (Ex: “*” retorna todos os arquivos, “*.txt” retorna todos os arquivos terminados com .txt, etc..)
Exemplo de uso:

Código-fonte:
using System.Data;
using System.Data.SqlTypes;
using System.Net;
using System.Threading;
using Microsoft.SqlServer.Server;
using Bibliotecas.Model;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Arquivo_Listar(SqlString host, SqlString pastaFtp, SqlString filtro, SqlString login, SqlString senha)
{
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
var arquivos = ftp.ListarArquivos(pastaFtp.Value, filtro.Value);
var pipe = SqlContext.Pipe;
var cols = new SqlMetaData[1];
cols[0] = new SqlMetaData("Nm_Arquivo", SqlDbType.NVarChar, 1024);
var rec = new SqlDataRecord(cols);
if (pipe == null) return;
pipe.SendResultsStart(rec);
foreach (var file in arquivos)
{
rec.SetSqlString(0, new SqlString(file));
pipe.SendResultsRow(rec);
}
pipe.SendResultsEnd();
sucesso = true;
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
};
Função para listar arquivos de um FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteAlém disso, ela pode ser utilizada facilmente para filtrar com WHERE, utilizar JOINS, ORDER BY, SELECT * INTO #Tabela, etc, dando muito mais flexibilidade na sua utilização em relação à Stored Procedure anterior.
Exemplo de uso:

Código-fonte:
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Net;
using System.Threading;
using Bibliotecas.Model;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction(
FillRowMethodName = "FillRow_FTP_Arquivos_Listar",
TableDefinition = "Nr_Linha INT, Fl_Tipo NVARCHAR(20), Nm_Diretorio NVARCHAR(500), Nm_Arquivo NVARCHAR(500), " +
"Qt_Tamanho BIGINT, Dt_Criacao DATETIME, Ds_Permissao NVARCHAR(20), Ds_Permissao_Octal NVARCHAR(4), " +
"Ds_Proprietario NVARCHAR(20), Ds_Grupo NVARCHAR(20)"
)]
public static IEnumerable fncFTP_Arquivos_Listar(string Ds_Hostname, string Ds_Usuario, string DsSenha, string Ds_Pasta_FTP, string Ds_Filtro)
{
var ftpArquivoListarCollection = new ArrayList();
if (string.IsNullOrEmpty(Ds_Hostname))
return ftpArquivoListarCollection;
var ftp = new FTPControle(Ds_Hostname, Ds_Usuario, DsSenha);
var arquivos = new List<string>();
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
arquivos = ftp.ListarArquivosCompleto(Ds_Pasta_FTP, Ds_Filtro);
sucesso = true;
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
var contador = 1;
foreach (var arquivo in arquivos)
{
if (arquivo.Substring(0, 1) != "d") continue;
var retorno = ftp.ListarArquivosCompleto_Parse(arquivo, Ds_Pasta_FTP, contador);
if (retorno.Nr_Linha.Value == 0) continue;
ftpArquivoListarCollection.Add(retorno);
contador++;
}
foreach (var arquivo in arquivos)
{
if (arquivo.Substring(0, 1) == "d") continue;
var retorno = ftp.ListarArquivosCompleto_Parse(arquivo, Ds_Pasta_FTP, contador);
ftpArquivoListarCollection.Add(retorno);
contador++;
}
return ftpArquivoListarCollection;
}
protected static void FillRow_FTP_Arquivos_Listar(object objFTPArquivoListar, out SqlInt32 nrLinha, out SqlString nmArquivo, out SqlString nmDiretorio, out SqlString flTipo, out SqlInt64 qtTamanho, out SqlDateTime dtCriacao, out SqlString dsPermissao, out SqlString dsPermissaoOctal, out SqlString dsProprietario, out SqlString dsGrupo)
{
var ftpArquivoListar = (FTPArquivoListar) objFTPArquivoListar;
nrLinha = ftpArquivoListar.Nr_Linha;
nmArquivo = ftpArquivoListar.Nm_Arquivo;
nmDiretorio = ftpArquivoListar.Nm_Diretorio;
flTipo = ftpArquivoListar.Fl_Tipo;
qtTamanho = ftpArquivoListar.Qt_Tamanho;
dtCriacao = ftpArquivoListar.Dt_Criacao;
dsPermissao = ftpArquivoListar.Ds_Permissao;
dsPermissaoOctal = ftpArquivoListar.Ds_Permissao_Octal;
dsProprietario = ftpArquivoListar.Ds_Proprietario;
dsGrupo = ftpArquivoListar.Ds_Grupo;
}
}
Como baixar um arquivo de um servidor FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteUm parâmetro especialmente útil, é o @apagarRemoto, que quando é informado o valor “1”, realiza o download dos arquivos que atendem aos critérios dos filtros informados e, logo em seguida, apaga esses arquivos do servidor FTP.
Exemplos de uso:

Fazendo o download de múltiplos arquivos utilizando filtros Wildcard
Código-fonte:
using System.Data.SqlTypes;
using System.IO;
using System.Net;
using System.Threading;
using Bibliotecas.Model;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Arquivo_Download(SqlString host, SqlString pastaFtp, SqlString filtro, SqlString login, SqlString senha, SqlString pastaLocal, SqlBoolean apagarRemoto)
{
#region tratamento de entradas
try
{
if (!Directory.Exists(pastaLocal.Value))
{
Retorno.Erro("Pasta local especificada não existe ou inacessivel.");
return;
}
}
catch
{
Retorno.Erro("Erro ao converter pasta local especificada.");
return;
}
#endregion
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
var arquivos = ftp.ListarArquivos(pastaFtp.Value, filtro.Value);
var qntArquivos = ftp.BaixarArquivos(pastaFtp.Value, arquivos, pastaLocal.Value);
if (apagarRemoto.Value)
{
ftp.ApagarArquivos(pastaFtp.Value, arquivos);
}
Retorno.Mensagem("Total de: (" + qntArquivos + ") arquivos foram baixados para: " + pastaLocal.Value);
sucesso = true;
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
};
Como enviar um arquivo para um servidor FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteNovamente, a SP permite especificar o nome do arquivo no parâmetro @filtro para enviar um arquivo específico, ou utilizar wildcards para realizar filtros em nomes de arquivos e enviar vários arquivos em uma única execução da Stored Procedure.
Exemplo de uso:

Enviando todos os arquivos com extensão “.txt” para o servidor FTP
Código-fonte:
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Net;
using System.Threading;
using Bibliotecas.Model;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Arquivo_Upload(SqlString host, SqlString pastaFtp, SqlString login, SqlString senha, SqlString pastaLocal, SqlString filtro)
{
#region tratamento de entradas
try
{
if (!Directory.Exists(pastaLocal.Value))
{
Retorno.Erro("Pasta local especificada não existe ou inacessivel.");
return;
}
}
catch
{
Retorno.Erro("Erro ao converter pasta local especificada.");
return;
}
List<string> listaArquivos;
try
{
var arquivos = Directory.GetFiles(pastaLocal.Value, filtro.Value);
listaArquivos = new List<string>(arquivos);
if (listaArquivos.Count == 0)
{
Retorno.Mensagem("(0) arquivos atendem o requisito de filtragem na pasta especificada.");
return;
}
}
catch
{
Retorno.Erro("Erro ao listar arquivos da pasta especificada.");
return;
}
#endregion
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
var qntArquivos = ftp.SubirArquivos(listaArquivos, pastaFtp.Value);
if (qntArquivos != -1)
{
Retorno.Mensagem("Total de: (" + qntArquivos + ") arquivos foram enviados para: " + pastaFtp.Value);
sucesso = true;
}
else
Retorno.Erro("Erro : Diretório do arquivo local inválido!");
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
}
Como criar um diretório em um servidor FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteUtilizando as funções de listar arquivos e diretórios, é possível identificar se o diretório desejado existe ou não, e caso não exista, criá-lo utilizando essa SP.
Exemplo de uso:

Código-fonte:
using System.Data.SqlTypes;
using Bibliotecas.Model;
using System.Net;
using System.Threading;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Cria_Diretorio(SqlString host, SqlString login, SqlString senha, SqlString pastaFtp)
{
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
using (var response = ftp.CriaDiretorio(pastaFtp.Value))
{
if (response.StatusCode == FtpStatusCode.PathnameCreated)
{
Retorno.Mensagem("Diretório " + pastaFtp.Value + " criado com sucesso");
sucesso = true;
}
else
{
Retorno.Erro(response.StatusDescription);
}
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
};
Como apagar um arquivo de um servidor FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteIsso não ocorre por impossibilidade técnica, apenas achei mais “seguro” não permitir apagar vários arquivos utilizando um filtro, mas nada que o impeça de alterar essa Procedure para permitir isso ou utilizar a Stored Procedure stpFTP_Apaga_Diretorio, que está logo abaixo.
Exemplo de uso:

Código-fonte:
using System.Data.SqlTypes;
using Bibliotecas.Model;
using System.Net;
using System.Threading;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Apaga_Arquivo(SqlString host, SqlString login, SqlString senha, SqlString pastaFtp, SqlString arquivoRemoto)
{
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
using (var response = ftp.ApagaArquivo(pastaFtp.Value, arquivoRemoto.Value))
{
if (response.StatusCode == FtpStatusCode.CommandOK || response.StatusCode == FtpStatusCode.FileActionOK)
{
Retorno.Mensagem("Arquivo " + pastaFtp.Value + "/" + arquivoRemoto.Value + " apagado com sucesso");
sucesso = true;
}
else
{
Retorno.Erro(response.StatusDescription);
}
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
};
Como apagar um diretório de um servidor FTP pelo SQL Server
Visualizar mais detalhes, exemplos de uso e código-fonteTenha em mente, que caso você informe o valor do parâmetro @apagarArquivos = 0 e houverem arquivos no diretório que você está tentando apagar, a SP irá retornar uma mensagem de erro informando que existem arquivos no diretório.
Exemplo de uso:

Código-fonte:
using System.Data.SqlTypes;
using Bibliotecas.Model;
using System.Net;
using System.Threading;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void stpFTP_Apaga_Diretorio(SqlString host, SqlString login, SqlString senha, SqlString pastaFtp, SqlBoolean apagaArquivos)
{
const int tentativas = 10;
var sucesso = false;
for (var i = 1; i <= tentativas; i++)
{
try
{
var ftp = new FTPControle(host.Value, login.Value, senha.Value);
using (var response = ftp.ApagaDiretorio(pastaFtp.Value, apagaArquivos.Value))
{
if (response.StatusCode == FtpStatusCode.FileActionOK)
{
Retorno.Mensagem("Diretório " + pastaFtp.Value + " apagado com sucesso");
sucesso = true;
}
else
{
Retorno.Erro(response.StatusDescription);
}
}
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.SendFailure || e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.PipelineFailure || e.Status == WebExceptionStatus.ConnectionClosed)
{
if (i < tentativas)
Retorno.Mensagem($"Erro na tentativa {i}: {e.Message}");
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
else
Retorno.Erro($"Erro : {e.Message}\n\nInner Exception: {e.InnerException}");
}
if (sucesso)
break;
Thread.Sleep(10000);
}
}
};
É isso aí, pessoal!
Espero que tenham gostado desse post e até mais!
sql server clr c# csharp baixar download ler read enviar subir upload arquivos files listar list integrar integrate integração integration servidor ftp server
sql server clr c# csharp baixar download ler read enviar subir upload arquivos files listar list integrar integrate integração integration servidor ftp server
Dirceu Resende
Arquiteto de Banco de Dados e BI · Microsoft MVP · MCSE, MCSA, MCT, MTA, MCP.
Posts relacionados
Carregando…


Comentários (0)
Carregando comentários…