解决文件路径过长异常的最佳方法


108

我创建了一个应用程序,可以下载SP网站中的所有文档库,但有一次它给了我这个错误(我尝试查看Google,但找不到任何东西,现在,如果有人知道解决此问题的任何技巧,请回复,否则,谢谢看看)

System.IO.PathTooLongException:指定的路径,文件名或两者都太长。完全限定的文件名必须少于260个字符,目录名称必须少于248个字符。在System.IO.Path.NormalizePathFast(字符串路径,布尔fullCheck)在System.IO.Path.GetFullPathInternal(字符串路径)在System.IO.FileStream.Init(字符串路径,FileMode模式,FileAccess访问,Int32权限,布尔useRights ,FileShare共享,Int32 bufferSize,FileOptions选项,SECURITY_ATTRIBUTES secAttrs,System.IO.FileStream..ctor(字符串路径,FileMode模式,FileAccess访问权限,FileShare共享,Int32 bufferSize,FileOptions选项)位于System.IO.FileStream..ctor。 IO.File.Create(字符串路径)

它达到了字符串的限制,代码如下所示,

#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

1
将UNC(或其他)路径转换为8.3格式。[使用CMD转换为8.3格式] [1] [1]:stackoverflow.com/questions/10227144/…–
AutomationNation


可能重复。在这里,我找到了解决方案stackoverflow.com/a/44211420/5312148
Francesco

Answers:


57

由于错误的原因很明显,因此以下一些信息应可帮助您解决问题:

请参阅有关命名文件,路径和命名空间的MS文章

这是链接的引文:

最大路径长度限制在Windows API(以下段落中讨论的某些例外情况)中,路径的最大长度为MAX_PATH,它定义为260个字符。本地路径按以下顺序构造:驱动器号,冒号,反斜杠,由反斜杠分隔的名称组件以及终止的空字符。例如,驱动器D上的最大路径是“ D:\一些256个字符的路径字符串<NUL>”,其中“ <NUL>”代表当前系统代码页的不可见终止空字符。(此处使用字符<>是为了清楚起见,并且不能成为有效路径字符串的一部分。)

和一些解决方法(摘自评论):

有解决各种问题的方法。下面列出的解决方案的基本思想始终是相同的:减小路径长度以具有path-length + name-length < MAX_PATH。你可以:

  • 共享一个子文件夹
  • 使用命令行通过SUBST分配驱动器号
  • 使用VB下的AddConnection将驱动器号分配给路径

7
@TimeToThine,您阅读我发表的文章了吗?您阅读评论了吗?我可能是错的,但是我认为除了我已经提供的内容之外,您不会从SO社区获得更多帮助。
詹姆斯·希尔

2
是的,我已经读过,在这里发表我的问题之前,我什至尝试过“ \\?\”,但由于某种原因,它在这种情况下不起作用。我找到了这个博客,正在使用它,但是由于某种原因,它无法正常工作,“ codinghorror.com/blog/2006/08/shortening-long-file-paths.html ”我仍然在寻找可以保存目录的东西,我可以从那里拿走它,或类似的东西,例如使用隐藏标签来保存当前目录,而不是字符串,但是不确定是否会起作用。
穆罕默德·拉贾

24
这是显而易见的,但没有任何意义。为什么会有路径大小限制???这是2017
。– Jaider

2
如果使用Directory.SetCurrentDirectory()将当前目录更改为文件夹的目录,它将避免此限制。还是问题仍然存在。
亚当·林赛

3
该文章似乎已更新:Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. 但是您必须选择加入,并设置一个注册表项来启用它。
汤姆·德布劳

28

对我有用的解决方案是编辑注册表项以启用长路径行为,将该值设置为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
我已经将此设置为1并仍然出现错误,这时不知道为什么。
先生愤怒

本文提到了两个要求。首先是注册表项,其次是应用程序xml:<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="https://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application>对于Visual Studio 2019中的我来说,在重新启动Visual Studio之后就不需要第二个要求。
汤姆·安德森

抱歉,这可能是愚蠢的问题,但是什么是“应用程序xml”?是web.config还是其他?我在网页asp.net项目上
遇到了

如上所述,它无需更改应用程序xml就可以在Visual Studio 2019中正常运行(重新启动后)。感谢您的解决方案。
Zoman

@TomAnderson:我正在使用VS2017。我在哪里可以找到此application.xml?因为执行第一步后无法解决我的问题。
莎拉德


3

您可以使用较短的目录创建符号链接。首先打开命令行,例如Shift + RightClick在所需的文件夹中使用较短的路径打开命令行(您可能必须以管理员身份运行它)。

然后输入相对或绝对路径:

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

然后从更短的路径开始解决方案。这里的优点是:您无需移动任何东西。


这在VS2015中不起作用。似乎VS正在预先验证路径的长度。有关VS2015的变通办法,请参阅N-Ate答案。
N-ate

1
您可以使用命令“ subst”将解决方案文件夹映射到驱动程序。适用于VS2017。
菲利普·卡拉桑斯

2

在Windows 8.1上,使用。NET 3.5,我有一个类似的问题。
尽管当我仅使用文件名(无路径)实例化FileInfo对象时,文件名的长度只有239个字符,却发生了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个字符(包括扩展名)的问题。


阅读此文件的任何人的其他信息-文件名限制为247个字符,而完整路径则限制为259个。因此,如果您的文件名是239个,则路径的其余部分仅保留20个字符(例如“ c:\ temp”) 。如果修剪文件名,则需要确保FULL路径为259个字符或更少。
Losbear

1

如果由于路径太长而使bin文件出现问题,则可以在Visual Studio 2015中转到有问题的项目的属性页,并将相对输出目录更改为较短的目录

例如bin \ debug \变成C:\ _ bins \ MyProject \


1
当我的构建失败时重新打开属性后,我注意到新路径“ c:\ vs \ bin \ Release”被替换为“ .. \ .. \ .. \ .. \ .. \ .. \ .. \\”。 。\ vs \ bin \ Release \“。我不确定“ .. \”是否会计入字符数。
samis

2
评估为太长的路径是绝对路径。
N-ate

1

对我有用的是将我的项目从桌面(C:\ Users \ lachezar.l \ Desktop \ MyFolder)移到(C:\ 0 \ MyFolder),如您所见,它使用较短的路径并减小了路径,从而解决了问题。


1

根据我的经验,对于任何面向公众的Web应用程序,我都不会推荐我的以下答案。

如果您将其用于内部工具或测试,则建议在您自己的计算机上共享它。

-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},这肯定比您希望的完整路径小得多,对我来说,我可以将其从290个字符减少到30个字符。:)


0

到目前为止没有提及和更新,这里有一个很好的建立库来处理过长的路径。AlphaFS是一个.NET库,它为.NET平台提供了比标准System.IO类更完整的Win32文件系统功能。标准.NET System.IO的最显着缺陷是缺乏对高级NTFS功能的支持,尤其是对扩展长度路径的支持(例如,文件/目录路径长于260个字符)。


0

我能找到的最佳答案是在这里的评论之一。将其添加到答案中,以便某人不会错过该评论,并且绝对应该尝试一下。它为我解决了这个问题。

我们需要使用命令提示符中的“ subst”命令将解决方案文件夹映射到驱动器,例如,subst z:

然后从该驱动器中打开解决方案(在这种情况下为z)。这将尽可能缩短路径,并可以解决冗长的文件名问题。


0

这有时也可能是解决方案。有时,当您将“开发”项目保留得太深时,也可能会发生,这意味着项目目录可能存在太多目录,因此请不要放置太多目录,将其保存在内部的简单文件夹中驱动器。例如-当我的项目保持这样时,我也收到此错误-

D:\ Sharad \ LatestWorkings \ GenericSurveyApplication020120 \ GenericSurveyApplication \ GenericSurveyApplication

然后我只是将项目粘贴到里面

D:\ Sharad \ LatestWorkings \ GenericSurveyApplication

解决了问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.