Hola, chicos,
¡Buenas tardes!
En esta publicación, hablaré nuevamente sobre CLR (C#), demostrando otro uso de esta poderosa característica de SQL Server, que es la integración entre la base de datos y los servidores FTP, ya sea para descargar (descargar) o cargar (cargar) archivos entre una carpeta local o en su red y el servidor FTP.
Esta característica es especialmente útil cuando necesita integraciones con otras empresas, donde necesita exportar datos y ponerlos a disposición en el FTP externo de otra empresa o importar archivos desde un FTP e importarlos a su red o base de datos.
Para devolver mensajes de advertencia y mensajes de error del CLR a la base de datos, uso la clase Return, que está disponible en la publicación. SQL Server: cómo enviar advertencias y mensajes de error a la base de datos usando CLR (C#) y es una dependencia de esta clase FTP.
En todas las rutinas coloqué un “reintento” de hasta 10 intentos en casos de falla de conexión o tiempo de espera, para que tu rutina no falle por alguna inestabilidad de la red (esto ya me ha ayudado MUCHO).
Si no conoces CLR o no sabes por dónde empezar, mira más accediendo al post Introducción a SQL CLR (Common Language Runtime) en SQL Server.
Clase base: FTPControle.cs
Ver más detalles, ejemplos de uso y código fuenteAunque el código es bastante grande, no es una clase compleja y puede entenderse fácilmente.
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;
}
}
}
Cómo enumerar archivos desde un FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteEl parámetro de filtro le permite ingresar el nombre del archivo que desea filtrar o usar un comodín para devolver solo los archivos que cumplen con los criterios especificados (por ejemplo: "*" devuelve todos los archivos, "*.txt" devuelve todos los archivos que terminan en .txt, etc.)
Ejemplo de uso:

Código fuente:
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);
}
}
};
Función para listar archivos desde un FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteAdemás, se puede usar fácilmente para filtrar con WHERE, usar JOINS, ORDER BY, SELECT * INTO #Table, etc., brindando mucha más flexibilidad en su uso en comparación con el procedimiento almacenado anterior.
Ejemplo de uso:

Código fuente:
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;
}
}
Cómo descargar un archivo desde un servidor FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteUn parámetro especialmente útil es @apagarRemoto, que cuando se introduce el valor “1”, descarga los archivos que cumplen con los criterios de filtro introducidos y luego elimina estos archivos del servidor FTP.
Ejemplos de uso:

Resultado final con archivos descargados desde FTP
Código fuente:
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);
}
}
};
Cómo enviar un archivo a un servidor FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteNuevamente, SP le permite especificar el nombre del archivo en el parámetro @filtro para enviar un archivo específico, o usar comodines para realizar filtros en los nombres de los archivos y enviar varios archivos en una sola ejecución del procedimiento almacenado.
Ejemplo de uso:

Subir todos los archivos con extensión “.txt” al servidor FTP
Código fuente:
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);
}
}
}
Cómo crear un directorio en un servidor FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteUsando las funciones para listar archivos y directorios, es posible identificar si el directorio deseado existe o no, y si no es así, crearlo usando este SP.
Ejemplo de uso:

Código fuente:
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);
}
}
};
Cómo eliminar un archivo de un servidor FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteEsto no se debe a una imposibilidad técnica, simplemente me pareció más “seguro” no permitir eliminar múltiples archivos usando un filtro, pero nada que impida cambiar este Procedimiento para permitir esto o usar el Procedimiento Almacenado stpFTP_Apaga_Diretorio, que está justo debajo.
Ejemplo de uso:

Código fuente:
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);
}
}
};
Cómo eliminar un directorio de un servidor FTP usando SQL Server
Ver más detalles, ejemplos de uso y código fuenteTenga en cuenta que si ingresa el valor del parámetro @apagarArquivos = 0 y hay archivos en el directorio que está intentando eliminar, SP devolverá un mensaje de error informándole que hay archivos en el directorio.
Ejemplo de uso:

Código fuente:
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);
}
}
};
¡Eso es todo, amigos!
Espero que hayas disfrutado de esta publicación y ¡hasta luego!
servidor sql clr c# csharp descargar descargar leer leer enviar cargar cargar archivos lista de archivos lista integrar integrar integración servidor de integración servidor ftp
servidor sql clr c# csharp descargar descargar leer leer enviar cargar cargar archivos lista de archivos lista integrar integrar integración servidor de integración servidor ftp
Dirceu Resende
Arquitecto de Bases de Datos y BI · Microsoft MVP · MCSE, MCSA, MCT, MTA, MCP.


Comentários (0)
Carregando comentários…