Подтвердить что ты не робот

Как избежать задачи SSIS FTP из-за сбоя, когда нет файлов для загрузки?

Я использую SQL Server 2005 и создаю ftp-задачи в SSIS.

Иногда будут файлы для ftp, иногда нет. Если файлов нет, я не хочу, чтобы задача или пакет не сработали. Я изменил стрелку, идущую от задачи ftp, до "завершения", поэтому пакет проходит. Я изменил допустимое количество ошибок на 4 (потому что есть 4 ftp задачи, и в любом из 4-х каталогов могут быть или нет файлы).

Но, когда я запускаю пакет из задания в агенте, он отмечает, что задание является неудачным. Поскольку это будет выполняться каждые 15 минут, я не хочу иметь кучу красного x в моей истории работы, что приведет к тому, что мы не увидим проблемы, когда это действительно произойдет.

Как установить свойства в задаче ftp, чтобы не находить файлы в ftp не является провалом? Операция, которую я использую, - "Отправить файлы".

Вот еще информация: файлы находятся на сервере, к которому у меня нет доступа, кроме ftp. И я не знаю имена файлов раньше времени. Пользователь может называть их все, что захочет. Поэтому я не могу проверить конкретные файлы, и, я думаю, я могу проверить вообще. За исключением использования соединения ftp и задач, основанных на этом соединении. Файлы находятся на удаленном сервере, и я хочу скопировать их на свой сервер, чтобы получить их с этого удаленного сервера.

Я могу установить командный уровень ftp в задаче script. Возможно, это то, что мне нужно использовать вместо задачи ftp. (Я изменил использование командной строки ftp с файлом параметров, вызванным из задачи script. Он не дает ошибок, когда нет файлов для получения. Я думаю, что это решение будет работать для меня. создавая файл параметров динамически, а это значит, что мне не нужно иметь информацию о соединении в текстовом файле, а может храниться в моем файле конфигурации, который находится в более безопасном месте.)

4b9b3361

Ответ 1

Проверьте ссылку , в которой описывается корректная обработка ошибки задачи в пакете SSIS.

У меня была почти такая же проблема, но с извлечением файлов. Я хотел, чтобы пакет НЕ завершился неудачей, если на FTP-сервере не было найдено файлов. Вышеупомянутая ссылка останавливает всплывающую ошибку и приводит к сбою пакета; что бы вы подумали, что FailPackageOnError = false должен был сделать?: -S

Надеюсь, что это тоже поможет вам!

Ответ 2

Я понимаю, что вы нашли ответ на свой вопрос. Это касается других пользователей, которые могут наткнуться на этот вопрос. Вот один из возможных способов достижения этого. Script Task можно использовать для поиска списка файлов, присутствующих в пути к папке FTP для данного шаблона (например, *.txt). Ниже приведен пример того, как это можно сделать.

Шаг за шагом:

  • В пакете SSIS создайте FTP Connection с именем FTP, а также создайте переменные 5, как показано на снимке экрана 1, Переменная RemotePath содержит путь к папке FTP; LocalPath содержит папку, в которой файлы будут сбрасываться; FilePattern содержит шаблон файла для поиска списка файлов для загрузки с FTP-сервера; FileName будет заполняться Foreach loop container, но чтобы избежать ошибки времени разработки задачи FTP, его можно заполнить с помощью / или свойства DelayValidation в задаче FTP можно установить на True.

  • В пакете SSIS поместите Script Task, Foreach loop container и FTP Task в Foreach loop container, как показано на скриншотах # 2.

  • Замените метод Main() в Script Task кодом в разделе Script Код задачи. Script Задача заполнит переменную ListOfFiles коллекцией файлов, соответствующих заданному шаблону. В этом примере сначала будет использоваться шаблон *.txt, который не даст никаких результатов, а затем и шаблон *.xls, который будет соответствовать нескольким файлам на FTP-сервере.

  • Настройте Foreach loop container, как показано на скриншотах # 3 и # 4. Эта задача будет проходить через переменную ** ListOfFiles *. Если файлов нет, задача FTP внутри контейнера цикла не будет выполняться. Если есть файлы, задача FTP внутри контейнера цикла будет выполняться для задачи для количества файлов, найденных на FTP-сервере.

  • Настройте FTP Task, как показано на скриншотах # 5 и # 6.

  • Снимок экрана # 7 показывает пример выполнения пакета, если для шаблона *.txt найдено нет совпадающих файлов.

  • Снимок экрана # 8 показывает содержимое папки C:\temp\ перед выполнением пакета.

  • Снимок экрана # 9 показывает пример выполнения пакета при поиске совпадающих файлов для шаблона *.xls.

  • Снимок экрана # 10 показывает содержимое пути удаленного FTP /Practice/Directory_New.

  • Снимок экрана # 11 показывает содержимое папки C:\temp\ после выполнения пакета.

  • Снимок экрана # 12 показывает сбой пакета при наличии неправильного Удаленного пути.

  • Снимок экрана # 13 показывает сообщение об ошибке, связанную с отказом пакета.

Надеюсь, что это поможет.

Script Код задачи:

С#, который можно использовать в 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:

1

Снимок экрана №2:

2

Снимок экрана №3: ​​

3

Снимок экрана №4:

4

Снимок экрана № 5:

5

Снимок экрана № 6:

6

Снимок экрана № 7:

7

Снимок экрана # 8:

8

Снимок экрана № 9:

9

Снимок экрана № 10:

10

Снимок экрана № 11:

11

Снимок экрана № 12:

<Т411 >

Снимок экрана № 13:

13

Ответ 3

У меня просто была эта проблема, после прочтения некоторых ответов здесь ничего действительно не разобралась в моей проблеме, и предлагаемые здесь решения выглядят безумными с точки зрения сложности.

Моя FTP-задача потерпела неудачу, так как я не разрешил перезаписывать файлы, скажем, что задание было начато дважды подряд, первый проход будет прекрасен, потому что некоторые файлы передаются, но не удастся, если локальный файл уже существует,

Мое решение было простым:

  • Задача правой кнопки мыши - Свойства
  • Установить ForceExecutionResult = "Успех"

Ответ 4

(Я не могу принять свой собственный ответ, но это было решение, которое сработало для меня.)

Это может быть не лучшее решение, но это работает.

Я использую задачу script и имею кучу переменных для информации о соединении 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 файл (в котором есть информация о подключении!).

Если файлы не существуют в исходном каталоге (переменная имеет\\диск\dir\*. * mapping), то ошибки нет. Если произошла какая-либо другая ошибка, задача все равно не работает, как и должно быть.

Я новичок в SSIS, и это может быть kludge. Но сейчас это работает. Наверное, я попросил лучшего, и я, конечно же, не буду утверждать, что это так.

Как я уже указывал, у меня нет возможности узнать, какие файлы названы, или даже там, где есть файлы. Если они есть, я хочу их получить.

Ответ 5

У меня нет пакетного ответа для вас, но поскольку никто еще ничего не опубликовал...

Вы должны иметь возможность установить переменную в задаче ActiveX script, а затем использовать ее для определения того, должна ли выполняться задача FTP. Ниже приведен пример , который работает с локальными путями. Надеюсь, вы сможете адаптировать концепцию (или, если возможно, сопоставить FTP-диск и сделать это именно так).

Ответ 6

Поместите его в контейнер ForEach, который выполняет итерацию над загружаемыми файлами. Нет файлов, нет FTP, без сбоев.

Ответ 7

Вы можете перенаправить на отказ, на другую задачу, которая ничего не делает, то есть script, которая возвращает true.

Чтобы сделать это, добавьте новую задачу script, выделите задачу FTP, появится второй зеленый коннектор, перетащите его в задачу script, а затем дважды щелкните по нему. Выберите "Отказ" в раскрывающемся списке "Значение". Очевидно, что вам придется обрабатывать реальные сбои в этой задаче script, чтобы по-прежнему отображаться прямо в истории заданий.

Ответ 8

Ага, ОК - Спасибо за разъяснение. Поскольку задача FTP не может вернуть список папок, невозможно будет использовать ForEach, как я изначально сказал. Это работает только в том случае, если вы загружаете X количество файлов в удаленный источник.

Чтобы загрузить X количество файлов, вы можете пойти двумя путями: либо вы можете полностью использовать его .Net в задаче script, либо вы можете заполнить ArrayList именами файлов из .Net script а затем ForEach через ArrayList, передав имя файла переменной и загрузив это имя переменной в стандартную задачу FTP.

Пример кода в соответствии с: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2472491&SiteID=1

Итак, в приведенном выше примере вы должны получить FileNames() и заполнить ArrayList, а затем назначьте ArrayList переменной типа Object в Dts.Variables, затем ForEach над этой переменной Object (ArrayList), используя код что-то например: http://www.sqlservercentral.com/articles/SSIS/64014/

Ответ 9

Вы можете использовать бесплатную задачу SSIS FTP Task ++ от eaSkills. Он не выдает ошибки, если файл или файлы не существует, он поддерживает wild cards и дает вам возможность загружать и удалять, если вам нужно это сделать.

Здесь ссылка на страницу функций: http://www.easkills.com/ssis/ftptask

Ответ 10

Это другое решение, которое работает для меня, используя встроенный материал и так без ручной перезаписи логики FTP:

1) Создайте переменную в пакете с именем FTP_Error

2) Нажмите "FTP-задача", затем нажмите вкладку "Обработчики событий"

3) Нажмите на странице, чтобы создать обработчик событий для "FTP Task/OnError" - это срабатывает всякий раз, когда возникают проблемы с FTP

4) На панели инструментов перетащите элемент Script Задачи и дважды щелкните, чтобы открыть это.

5) В первом всплывающем окне ReadOnlyVariables - добавьте System:: ErrorCode, System:: ErrorDescription

6) В первом всплывающем окне ReadWriteVariables - добавьте переменную User:: FTP_Error

7) Изменить Script

8) В Script установите для параметра FTP_Error значение ReadOnlyVariables, которое у нас было выше:

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

9) Сохранить и закрыть Script

10) Нажмите "ОК" на Script задачу

11) Вернитесь на вкладку "Контроль потока"

12) Из задачи FTP OnError перейдите к новой задаче Script и отредактируйте ее

13) ReadOnlyVariables: Пользователь:: FTP_Error из

14) Теперь, когда на FTP нет файлов, код ошибки -1073573501 (здесь вы можете найти список ссылок на код ошибки: http://msdn.microsoft.com/en-us/library/ms345164.aspx)

15) В вашем script введите логику, чтобы делать то, что вы хотите - если вы найдете код "без файлов", возможно, вы скажете, что задача выполнена успешно. Если нет, то задача не выполнена. И ваш нормальный поток может справиться с этим, как вы пожелаете:

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

И оттуда ваш поток Succeeded/Failed сделает то, что вы хотите с ним сделать.

Ответ 11

Альтернативой является использование этого FTP File Enumerator enter image description here