Лучший способ разрешить путь к файлу слишком длинное исключение - PullRequest
88 голосов
/ 05 января 2012

Я создал приложение, которое загружает все библиотеки документов на SP-сайте, но однажды оно выдает мне эту ошибку (я пытался посмотреть на Google, но ничего не смог найти, теперь, если кто-нибудь знает какой-либо трюк для решения этой проблемы, пожалуйста,Ответьте иначе, спасибо за просмотр)

System.IO.PathTooLongException: указанный путь, имя файла или оба слишком длинные.Полное имя файла должно быть не более 260 символов, а имя каталога должно быть не более 248 символов.в System.IO.Path.NormalizePathFast (строковый путь, Boolean fullCheck) в System.IO.Path.GetFullPathInternal (строковый путь) в System.IO.FileStream.Init (строковый путь, режим FileMode, доступ к FileAccess, права Int32, логическое использование useRights, FileShare, Int32 bufferSize, параметры FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) в System.IO.FileStream..ctor (путь строки, режим FileMode, доступ к FileAccess, общий ресурс FileShare, Int32 bufferSize, параметры FileOptions) в системе.IO.File.Create (String path)

достигает предела для строки, код указан ниже,

#region Downloading Schemes

    private void btnDownload_Click(object sender, EventArgs e)
    {
        TreeNode currentNode = tvWebs.SelectedNode;
        SPObjectData objectData = (SPObjectData)currentNode.Tag;
        try
        {
            CreateLoggingFile();
            using (SPWeb TopLevelWeb = objectData.Web)
            {
                if(TopLevelWeb != null)
                    dwnEachWeb(TopLevelWeb, TopLevelWeb.Title, tbDirectory.Text);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(string.Format("Exception caught when tried to pass TopLevelWeb:{1}, Title = {2}, object data to (dwnEachWeb_method), Exception: {0}", ex.ToString(), objectData.Web, objectData.Title));
        }
        finally
        {
            CloseLoggingFile();
        }
    }

    private void dwnEachWeb(SPWeb TopLevelWeb, string FolderName, string CurrentDirectory)
    {
        if (TopLevelWeb != null)
        {
            if (TopLevelWeb.Webs != null)
            {
                CurrentDirectory = CurrentDirectory + "\\" + TopLevelWeb.Title;
                CreateFolder(CurrentDirectory);
                foreach (SPWeb ChildWeb in TopLevelWeb.Webs)
                {

                    dwnEachWeb(ChildWeb, ChildWeb.Title, CurrentDirectory);
                    ChildWeb.Dispose();
                }
                dwnEachList(TopLevelWeb, CurrentDirectory);
                //dwnEachList(TopLevelWeb, FolderName, CurrentDirectory);
            }
        }
    }

    private void dwnEachList(SPWeb oWeb, string CurrentDirectory)
    {
        foreach (SPList oList in oWeb.Lists)
        {
            if (oList is SPDocumentLibrary && !oList.Hidden)
            {
                dwnEachFile(oList.RootFolder, CurrentDirectory);
            }
        }
    }

    private void dwnEachFile(SPFolder oFolder, string CurrentDirectory)
    {
        if (oFolder.Files.Count != 0)
        {
            CurrentDirectory = CurrentDirectory + "\\" + oFolder.Name;
            CreateFolder(CurrentDirectory);
            foreach (SPFile ofile in oFolder.Files)
            {
                if (CreateDirectoryStructure(CurrentDirectory, ofile.Url))
                {
                    var filepath = System.IO.Path.Combine(CurrentDirectory, ofile.Url);
                    byte[] binFile = ofile.OpenBinary();
                    System.IO.FileStream fstream = System.IO.File.Create(filepath);
                    fstream.Write(binFile, 0, binFile.Length);
                    fstream.Close();
                }
            }
        }
    }

    //creating directory where files will be download        
    private bool CreateDirectoryStructure(string baseFolder, string filepath)
    {
        if (!Directory.Exists(baseFolder)) return false;

        var paths = filepath.Split('/');

        for (var i = 0; i < paths.Length - 1; i++)
        {
            baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
            Directory.CreateDirectory(baseFolder);
        }
        return true;
    }

    //creating folders
    private bool CreateFolder(string CurrentDirectory)
    {
        if (!Directory.Exists(CurrentDirectory))
        {
            Directory.CreateDirectory(CurrentDirectory);
        }
        return true;
    }

    //shorting string

    #endregion

Ответы [ 11 ]

51 голосов
/ 05 января 2012

Поскольку причина ошибки очевидна, вот некоторая информация, которая должна помочь вам решить проблему:

См. Эту статью MS о именовании файлов, путей и пространств имен

Вот цитата из ссылки:

Ограничение максимальной длины пути В Windows API (с некоторыми исключениями, обсуждаемыми в следующих параграфах), максимальная длина путиMAX_PATH, который определен как 260 символов.Локальный путь структурируется в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имен, разделенные обратной косой чертой, и завершающий нулевой символ.Например, максимальный путь на диске D равен «D: \ some 256-символьная строка пути », где «» представляет невидимый завершающий нулевой символ для текущей системной кодовой страницы.(Символы <> используются здесь для наглядности и не могут быть частью допустимой строки пути.)

И несколько обходных путей (по комментариям):

Естьспособы решения различных проблем.Основная идея решений, перечисленных ниже, всегда одна и та же: уменьшите длину пути, чтобы получить path-length + name-length < MAX_PATH.Вы можете:

  • Поделиться подпапкой
  • Использовать командную строку для назначения буквы диска с помощью SUBST
  • Использовать AddConnection в VB для назначения буквы диска дляпуть
23 голосов
/ 13 января 2013

Есть библиотека с именем Zeta Long Paths , которая предоставляет API .NET для работы с длинными путями.

Вот хорошая статья, которая охватывает эту проблему как для .NET, так и для PowerShell: .NET, слишком длинный путь PowerShell, исключение и .NET PowerShell Robocopy Clone"

12 голосов
/ 12 октября 2018

Решение, которое работало для меня, состояло в том, чтобы отредактировать ключ реестра, чтобы включить поведение длинного пути, установив значение 1. Это новая функция выбора для Windows 10

HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD)

Я получил это решение из названного раздела статьи, которую опубликовал @ james-hill.

https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

2 голосов
/ 17 июня 2017

Вы можете создать символическую ссылку с более коротким каталогом. Сначала откройте командную строку , например, Shift + RightClick в нужной папке с более коротким путем (возможно, вам придется запустить ее как администратор).

Затем введите с относительными или абсолютными путями:

mklink ShortPath\To\YourLinkedSolution C:\Path\To\Your\Solution /D

А затем начните Решение с более короткого пути. Преимущество здесь: вам не нужно ничего перемещать.

2 голосов
/ 22 января 2014

На Windows 8.1, используя. NET 3.5, у меня была похожая проблема.
Хотя имя моего файла было длиной всего 239 символов, когда я пошел, чтобы создать экземпляр объекта FileInfo только с именем файла (без пути), произошло исключение типа System. IO.PathTooLongException

2014-01-22 11:10:35 DEBUG LogicalDOCOutlookAddIn.LogicalDOCAddIn - fileName.Length: 239 
2014-01-22 11:10:35 ERROR LogicalDOCOutlookAddIn.LogicalDOCAddIn - Exception in ImportEmail System.IO.PathTooLongException: Percorso e/o nome di file specificato troppo lungo. Il nome di file completo deve contenere meno di 260 caratteri, mentre il nome di directory deve contenere meno di 248 caratteri.
   in System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
   in System.IO.FileInfo..ctor(String fileName)
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.GetTempFilePath(String fileName) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 692
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmail(_MailItem mailItem, OutlookConfigXML configXML, Int64 targetFolderID, String SID) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 857
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmails(Explorers explorers, OutlookConfigXML configXML, Int64 targetFolderID, Boolean suppressResultMB) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 99

Я решил проблему с обрезкой имени файла до 204 символов (включая расширение).

1 голос
/ 22 июня 2018

Что сработало для меня, так это перемещение моего проекта на рабочем столе (C: \ Users \ lachezar.l \ Desktop \ MyFolder) в (C: \ 0 \ MyFolder), который, как вы можете видеть, использует более короткий путь и сокращаетэто решило проблему.

1 голос
/ 12 марта 2018

Если у вас возникла проблема с файлами bin из-за длинного пути, в Visual Studio 2015 вы можете перейти на страницу свойств проекта-нарушителя и изменить относительный Выходной каталог короче.

например. bin \ debug \ становится C: \ _ bins \ MyProject \

0 голосов
/ 15 июля 2019

Исходя из моего опыта, я не буду рекомендовать мой ответ ниже для любых общедоступных веб-приложений.

Если вам это нужно для собственных инструментов или для тестирования, я бы порекомендовал поделиться им на своем компьютере.

-Right click on the root path you need to access
-Choose Properties
-Click on Share button and add your chosen users who can access it

После этого будет создан общий каталог, такой как \\ {PCName} \ {YourSharedRootDirectory}. Это может быть намного меньше, чем ваш полный путь. Надеюсь, для себя я мог бы сократить до 30 символов с 290персонажи.:)

0 голосов
/ 30 апреля 2019

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

Нам нужно сопоставить папку решения с диском с помощью команды "subst" в командной строке - например, subst z:

, а затем открыть решение изэтот диск (z в данном случае).Это максимально сократило бы путь и могло бы решить проблему длинного имени файла.

0 голосов
/ 25 февраля 2019

Пока не упомянуто и об обновлении, есть очень хорошая библиотека для обработки слишком длинных путей. AlphaFS - это библиотека .NET, предоставляющая более полную функциональность файловой системы Win32 для платформы .NET, чем стандартные классы System.IO. Наиболее заметным недостатком стандартного .NET System.IO является отсутствие поддержки расширенных функций NTFS, в частности, поддержка расширенных путей (например, пути к файлам / каталогам длиннее 260 символов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...