如何避免在没有文件下载失败的SSIS FTP任务?(How to avoid SSIS FTP ta

2019-07-17 16:42发布

我使用的是SQL Server 2005中,并创建SSIS中的FTP任务。

有时会有文件到FTP了,有时没有。 如果没有文件,我不想工作,也没有包失败。 我已经改变了箭头从FTP任务去旁边的“完成”,所以包贯穿。 我已经改变了错误的允许数量为4(因为有4个FTP任务,任何的4个目录可能会或可能不会有文件)。

但是,当我在代理作业运行包,它标志着工作作为失败。 由于这将是每15分钟一趟,我不想一堆红色的X在我的工作经历,这将导致当它确实发生我们没有看到一个问题。

如何设置FTP任务的属性,以便没有找到文件到FTP不是一个失败? 我使用的操作是“发送文件”。

下面是一些更多的信息:该文件是我没有任何访问都通过FTP之外的服务器上。 而且,我不知道文件名的时间提前。 用户可以打电话给他们为所欲为。 因此,我不能检查特定的文件,也没有,我想,我可以检查的。 除了通过使用基于该连接的FTP连接和任务。 该文件是在远程服务器上,我想他们在复制到我的服务器,从该远程服务器获取它们。

我可以在脚本任务外壳命令级别的FTP。 也许这就是我需要使用,而不是FTP任务。 (我已经改变使用FTP命令行,以参数文件,从脚本任务调用。当没有文件就搞定了。我觉得这个解决方案是要为我工作。我创造了它没有给出错误动态参数文件,这意味着我不需要在纯文本文件的连接信息,而是可以存储在我的配置文件,它是在一个更安全的地方。)

Answer 1:

我明白,你已经找到了问题的答案。 这是就这个问题谁可能绊倒其他用户。 下面是实现这一目标的一个可能的方式。 Script Task可以用来找到一个给定模式存在的FTP文件夹路径的文件列表(比如*.txt )。 下面的示例演示如何可以做到这一点。

一步一步的过程:

  1. 上SSIS包,创建一个FTP Connection命名FTP并且如图截图#1还创建5个变量。 可变RemotePath包含FTP文件夹路径; LocalPath包含其中的文件将被downloaed文件夹; FilePattern包含文件模式来查找文件从FTP服务器下载的列表; FileName会被填充Foreach loop container但要避免FTP任务设计时错误,它可以与填充/DelayValidation对FTP任务属性可以设置为True。

  2. 上SSIS包,放置一个Script TaskForeach Loop containerFTP Task的内Foreach Loop container中所示的屏幕截图#2。

  3. 取代Main()的内方法Script Task与下脚本任务代码部分的代码。 脚本任务将填充变量ListOfFiles匹配给定模式的文件的集合。 这个例子将首先使用模式* .TXT,这样产生的结果,然后后来模式的* .xls,将匹配在FTP服务器上一些文件。

  4. 配置Foreach Loop container中所示的屏幕截图#3#4。 此任务将通过可变** ListOfFiles循环*。 如果没有文件,循环容器内的FTP任务将不会执行。 如果有文件,循环容器内的FTP任务将执行针对FTP服务器上找到的文件数量的任务。

  5. 配置FTP Task如图截图#5#6。

  6. 截图#7示出了示例包执行时没有匹配的文件中找到的图案*.txt

  7. 截图#8示出了文件夹的内容C:\temp\包的执行之前

  8. 截图#9示出了示例包时执行匹配文件中找到该模式*.xls

  9. 截图#10示出了FTP远程路径的内容/Practice/Directory_New

  10. 截图#11示出了文件夹的内容C:\temp\包的执行之后

  11. 屏幕截图12显示封装失效时,不正确的远程路径上。

  12. 截图#13示出了与包失败的错误消息。

希望帮助。

脚本任务代码:

可以在使用C#代码SSIS 2008 and above

包括using 使用System.Text.RegularExpressions声明;

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

VB代码,可以用在SSIS 2005 and above

包括Imports语句导入System.Text.RegularExpressions

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

截图#1:

屏幕截图2:

屏幕截图3:

屏幕截图4:

截图#5:

屏幕截图6:

截图#7:

屏幕截图8:

截图#9:

屏幕截图10:

屏幕截图11:

屏幕截图12:

屏幕截图13:



Answer 2:

检查此链接 ,描述关于适当地处理任务的错误在SSIS包。

我几乎同样的问题,但是,与检索文件。 我想包时FTP服务器上没有发现文件不失败。 以上的链接停止错误冒泡以及使所述包失败; 东西你会想到FailPackageOnError =假应该做的? :-S

希望这也解决了它为您服务!



Answer 3:

我只是有这个问题,阅读一些答复这里经过,没有什么能跟我的问题和解决方案在这里在复杂性方面显得疯狂。

我的FTP任务失败,因为我没有允许覆盖文件,可以说工作是在一排拉开序幕两次,第一遍会被罚款,因为一些文件被转移了,但如果本地文件已经存在,就会失败。

我的解决方案很简单:

  1. 右键单击任务 - 属性
  2. 设置ForceExecutionResult =“成功”


Answer 4:

(我不能接受我自己的答案,但是这是为我工作的解决方案。)

它可能不是最好的解决办法,但这个工程。

我使用脚本任务,有一堆的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文件(已在它的连接信息!)。

如果源目录中不存在的文件(该变量的\\驱动器\目录\ *。*映射),那么就没有错误。 如果某些其他错误发生,任务仍然失败,因为它应该。

我是新来的SSIS,这可能是一个杂牌。 但是,它适用于现在。 我想我问的最佳方式,我就肯定不会声称这是它。

正如我指出的那样,我不知道什么是文件命名,或者即使有任何文件存在一样的方式。 如果他们在那里,我想他们。



Answer 5:

我没有打包的答案,但因为没有其他人发布任何...

您应该能够设置一个变量在一个ActiveX脚本任务,然后用它来决定FTP任务是否应该运行。 有一个例子在这里 ,与本地路径的作品。 希望你能适应的概念(或如果可能的话,映射FTP驱动器和这样做的)。



Answer 6:

1)设置FTP任务属性ForceExecutionResult =成功

2)该代码添加到FTP任务OnError事件处理程序。

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


Answer 7:

把它放在一个Foreach容器,在文件迭代上传哪些。 没有文件,没有FTP,没有失败。



Answer 8:

您可以在失败重定向到一个什么也不做,即只返回true脚本的另一个任务。

要做到这一点,添加新的脚本任务,突出你的FTP任务,第二次绿色连接将出现,这拖到脚本任务,然后双击它。 在价值选择失败降下来了。 显然,您则需要处理真正的失败,在此脚本任务就在作业历史记录仍然显示。



Answer 9:

啊哈,OK - 感谢澄清。 由于FTP任务不能返回一个文件夹列表,将不可能使用ForEach就像我一开始说的 - 那只有当你要上传的文件X量到远程源工作。

要下载文件的X量,你可以去两种方式,要么你可以在脚本任务全部做在.NET中,也可以从.NET脚本任务中通过的ArrayList填充文件名的ArrayList,那么的ForEach ,传递文件名的变量和一个标准的FTP任务下载该变量名。

代码示例,以适应: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2472491&SiteID=1

:那么,在上面,你会得到的文件名()和填充从ArrayList中,ArrayList然后使用代码类似分配给Dts.Variables,然后过的ForEach对象是(ArrayList的)变量的对象类型变量的HTTP ://www.sqlservercentral.com/articles/SSIS/64014/



Answer 10:

您可以从eaSkills使用免费的SSIS FTP任务++。 它不会抛出一个错误,如果该文件或文件不存在,它支持通配符并为您提供下载,如果你需要的话删除选项。

这里的链接到专题页面: http://www.easkills.com/ssis/ftptask



Answer 11:

这是为我工作,使用内置的东西,因此无需手动重新写入FTP逻辑另一种解决方案:

1)创建你的包称为可变FTP_Error

2)单击您的FTP任务,然后单击“事件处理程序”选项卡

3)单击页面内创建“FTP任务/的OnError”的事件处理程序 - 每当有与FTP麻烦这会火

4)从工具箱中,脚本任务物品拖动,双击打开了

5)在第一个弹出,ReadOnlyVariables - 添加系统::错误代码,系统:: ErrorDescription中

6)在第一个弹出,ReadWriteVariables - 添加用户:: FTP_Error变量

7)编辑脚本

8)在脚本设置你的FTP_Error变量来保存我们上面有ReadOnlyVariables:

Dts.Variables["FTP_Error"].Value = "ErrorCode:" + Dts.Variables["ErrorCode"].Value.ToString() + ", ErrorDescription=" + Dts.Variables["ErrorDescription"].Value.ToString();

9)保存并关闭脚本

10)点击“确定”脚本任务

11)返回到“控制流”选项卡

12)从FTP任务的OnError去一个新的脚本任务,并编辑

13)ReadOnlyVariables:用户:: FTP_Error从之前

14)现在,当没有对FTP找到的文件,错误代码为-1073573501(你可以在这里找到错误代码引用列表: http://msdn.microsoft.com/en-us/library/ms345164.aspx )

15)在你的脚本,放在逻辑做你想做什么 - 如果你找到一个“找不到文件”的代码,那么也许你说的任务成功。 如果没有,则任务失败。 而当你希望你的正常流动可以处理这个问题:

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

并从那里你的成功/失败的流动会做你想用它做什么。



Answer 12:

另一种方法是使用FTP文件枚举



文章来源: How to avoid SSIS FTP task from failing when there are no files to download?