Sql server 当没有可下载的文件时,如何避免SSIS FTP任务失败?
我正在使用SQLServer2005,并在SSIS中创建ftp任务 有时会有文件通过ftp传输,有时不会。如果没有文件,我不希望任务或包失败。我将ftp任务中的箭头改为下一个“completion”,这样包就可以运行了。我已将允许的错误数更改为4(因为有4个ftp任务,4个目录中的任何一个都可能有文件,也可能没有文件) 但是,当我从代理中的作业运行包时,它会将作业标记为失败。由于这将每15分钟运行一次,我不希望在我的工作历史中出现一堆红色的x,这将导致我们在问题真正发生时看不到问题 如何在ftp任务中设置属性,以便不将文件查找到ftp不会失败?我使用的操作是“发送文件” 这里有更多的信息:这些文件位于一个服务器上,除了ftp之外,我没有任何访问权限。而且,我事先不知道文件名。用户可以随意调用它们。所以我不能检查具体的文件,我想我也不能检查。除非通过使用ftp连接和基于该连接的任务。这些文件位于远程服务器上,我想将它们复制到我的服务器上,以便从远程服务器获取它们Sql server 当没有可下载的文件时,如何避免SSIS FTP任务失败?,sql-server,ssis,ftp,Sql Server,Ssis,Ftp,我正在使用SQLServer2005,并在SSIS中创建ftp任务 有时会有文件通过ftp传输,有时不会。如果没有文件,我不希望任务或包失败。我将ftp任务中的箭头改为下一个“completion”,这样包就可以运行了。我已将允许的错误数更改为4(因为有4个ftp任务,4个目录中的任何一个都可能有文件,也可能没有文件) 但是,当我从代理中的作业运行包时,它会将作业标记为失败。由于这将每15分钟运行一次,我不希望在我的工作历史中出现一堆红色的x,这将导致我们在问题真正发生时看不到问题 如何在ftp
我可以在脚本任务中shell命令级ftp。也许这就是我需要使用的,而不是ftp任务。(我已改为使用ftp命令行,其中包含一个从脚本任务调用的参数文件。当没有文件可获取时,该命令行不会出错。我认为该解决方案适合我。我正在动态创建参数文件,这意味着我不需要在纯文本文件中包含连接信息,而是可以存储在我的配置文件,它在一个更安全的位置。)我没有一个打包的答案给你,但是因为还没有其他人发布任何东西
您应该能够在ActiveX脚本任务中设置一个变量,然后使用该变量来决定是否应该运行FTP任务。有一个使用本地路径的示例。希望您可以调整这个概念(或者,如果可能,映射FTP驱动器并以这种方式执行)。将其放入ForEach容器中,该容器将迭代要上载的文件。无文件、无FTP、无故障。您可以在出现故障时重定向到另一个不执行任何操作的任务,即返回true的脚本
为此,添加新的脚本任务,突出显示FTP任务,第二个绿色连接器将出现,将其拖动到脚本任务,然后双击它。在“值”下拉列表中选择“失败”。显然,您将需要处理此脚本任务中的实际失败,以便仍然显示在作业历史记录中。Aha,好的-感谢您的澄清。由于FTP任务无法返回文件夹列表,因此不可能像我最初所说的那样使用ForEach-这仅在将X个文件上载到远程源时有效 要下载X数量的文件,可以采用两种方法,一种是在脚本任务中完全在.Net中完成,另一种是在.Net脚本任务中使用文件名填充ArrayList,然后在ArrayList上进行ForEach,将文件名传递给一个变量,然后在标准FTP任务中下载该变量名 适用的代码示例: 因此,在上面,您将获得FileNames()并从中填充ArrayList,然后将ArrayList分配给Dts.Variables中的一个对象类型变量,然后使用类似以下代码对该对象(ArrayList)变量进行ForEach:(我不能接受我自己的答案,但这是对我有效的解决方案。) 这可能不是最好的解决方案,但这是可行的 我使用了一个脚本任务,并为ftp连接信息、源目录和目标目录提供了一组变量。(因为,我们将更改运行此操作的服务器,并且在配置包中进行更改会更容易。) 我动态创建一个文本文件,并将ftp命令写入其中:
Dim ftpStream As StreamWriter = ftpFile.CreateText()
ftpStream.WriteLine(ftpUser)
ftpStream.WriteLine(ftpPassword)
ftpStream.WriteLine("prompt off")
ftpStream.WriteLine("binary")
ftpStream.WriteLine("cd " & ftpDestDir)
ftpStream.WriteLine("mput " & ftpSourceDir)
ftpStream.WriteLine("quit 130")
ftpStream.Close()
然后,在给它足够的时间真正关闭之后,我启动一个进程来执行ftp命令:
ftpParameters = "-s:" & ftpParameterLoc & ftpParameterFile & " " & ftpServer
proc = System.Diagnostics.Process.Start("ftp", ftpParameters)
然后,在给它更多的时间让ftp进程运行之后,我删除了临时ftp文件(其中包含连接信息!)
如果源目录中不存在文件(变量具有\\drive\dir\*.*映射),则没有错误。如果发生其他错误,任务仍然会失败,这是应该的
我是SSIS的新手,这可能是个难题。但它现在起作用了。我想我要求的是最好的方法,我当然不会声称这就是最好的方法
正如我指出的,我无法知道这些文件的名称,甚至根本不知道那里是否有任何文件。如果它们在那里,我想得到它们。检查这篇文章,它描述了如何优雅地处理SSIS包中的任务错误
我几乎有同样的问题,但检索文件。我希望在FTP服务器上找不到文件时,包不会失败。上面的链接阻止错误冒泡并导致包失败;您可能认为FailPackageError=false应该执行的操作?:-
希望这也能帮你解决 您可以使用eaSkills提供的免费SSIS FTP任务+。如果一个或多个文件不存在,它不会抛出错误,它支持通配符,并提供下载和删除选项(如果需要) 以下是指向功能页的链接:
我知道您已经找到了问题的答案。这是为其他可能偶然发现这个问题的用户准备的。以下是实现这一目标的一种可能方法<代码>脚本任务可用于查找给定模式的FTP文件夹路径中存在的文件列表(例如
*.txt
)。下面的示例显示了如何做到这一点
逐步过程:
FTP连接
public void Main()
{
Variables varCollection = null;
ConnectionManager ftpManager = null;
FtpClientConnection ftpConnection = null;
string[] fileNames = null;
string[] folderNames = null;
System.Collections.ArrayList listOfFiles = null;
string remotePath = string.Empty;
string filePattern = string.Empty;
Regex regexp;
int counter;
Dts.VariableDispenser.LockForWrite("User::RemotePath");
Dts.VariableDispenser.LockForWrite("User::FilePattern");
Dts.VariableDispenser.LockForWrite("User::ListOfFiles");
Dts.VariableDispenser.GetVariables(ref varCollection);
try
{
remotePath = varCollection["User::RemotePath"].Value.ToString();
filePattern = varCollection["User::FilePattern"].Value.ToString();
ftpManager = Dts.Connections["FTP"];
ftpConnection = new FtpClientConnection(ftpManager.AcquireConnection(null));
ftpConnection.Connect();
ftpConnection.SetWorkingDirectory(remotePath);
ftpConnection.GetListing(out folderNames, out fileNames);
ftpConnection.Close();
listOfFiles = new System.Collections.ArrayList();
if (fileNames != null)
{
regexp = new Regex("^" + filePattern + "$");
for (counter = 0; counter <= fileNames.GetUpperBound(0); counter++)
{
if (regexp.IsMatch(fileNames[counter]))
{
listOfFiles.Add(remotePath + fileNames[counter]);
}
}
}
varCollection["User::ListOfFiles"].Value = listOfFiles;
}
catch (Exception ex)
{
Dts.Events.FireError(-1, string.Empty, ex.ToString(), string.Empty, 0);
Dts.TaskResult = (int) ScriptResults.Failure;
}
finally
{
varCollection.Unlock();
ftpConnection = null;
ftpManager = null;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Public Sub Main()
Dim varCollection As Variables = Nothing
Dim ftpManager As ConnectionManager = Nothing
Dim ftpConnection As FtpClientConnection = Nothing
Dim fileNames() As String = Nothing
Dim folderNames() As String = Nothing
Dim listOfFiles As Collections.ArrayList
Dim remotePath As String = String.Empty
Dim filePattern As String = String.Empty
Dim regexp As Regex
Dim counter As Integer
Dts.VariableDispenser.LockForRead("User::RemotePath")
Dts.VariableDispenser.LockForRead("User::FilePattern")
Dts.VariableDispenser.LockForWrite("User::ListOfFiles")
Dts.VariableDispenser.GetVariables(varCollection)
Try
remotePath = varCollection("User::RemotePath").Value.ToString()
filePattern = varCollection("User::FilePattern").Value.ToString()
ftpManager = Dts.Connections("FTP")
ftpConnection = New FtpClientConnection(ftpManager.AcquireConnection(Nothing))
ftpConnection.Connect()
ftpConnection.SetWorkingDirectory(remotePath)
ftpConnection.GetListing(folderNames, fileNames)
ftpConnection.Close()
listOfFiles = New Collections.ArrayList()
If fileNames IsNot Nothing Then
regexp = New Regex("^" & filePattern & "$")
For counter = 0 To fileNames.GetUpperBound(0)
If regexp.IsMatch(fileNames(counter)) Then
listOfFiles.Add(remotePath & fileNames(counter))
End If
Next counter
End If
varCollection("User::ListOfFiles").Value = listOfFiles
Dts.TaskResult = ScriptResults.Success
Catch ex As Exception
Dts.Events.FireError(-1, String.Empty, ex.ToString(), String.Empty, 0)
Dts.TaskResult = ScriptResults.Failure
Finally
varCollection.Unlock()
ftpConnection = Nothing
ftpManager = Nothing
End Try
Dts.TaskResult = ScriptResults.Success
End Sub
Dts.Variables["FTP_Error"].Value = "ErrorCode:" + Dts.Variables["ErrorCode"].Value.ToString() + ", ErrorDescription=" + Dts.Variables["ErrorDescription"].Value.ToString();
if (Dts.Variables["FTP_Error"].Value.ToString().Contains("-1073573501"))
{
// file not found - not a problem
Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
// some other error - raise alarm!
Dts.TaskResult = (int)ScriptResults.Failure;
}
public void Main()
{
// TODO: Add your code here
int errorCode = (int)Dts.Variables["System::ErrorCode"].Value;
if (errorCode.ToString().Equals("-1073573501"))
{
Dts.Variables["System::Propagate"].Value = false;
}
else
{
Dts.Variables["System::Propagate"].Value = true;
}
Dts.TaskResult = (int)ScriptResults.Success;
}