Cách tốt nhất để giải quyết ngoại lệ đường dẫn tệp quá dài


109

Tôi đã tạo một ứng dụng tải xuống tất cả các thư viện tài liệu trong Trang web SP, nhưng tại một thời điểm nó cho tôi lỗi này (Tôi đã thử tìm kiếm trên google nhưng không thể tìm thấy gì cả, bây giờ nếu có ai biết bất kỳ thủ thuật nào để giải quyết vấn đề này, vui lòng trả lời nếu không, cảm ơn để nhìn nó)

System.IO.PathTooLongException: Đường dẫn được chỉ định, tên tệp hoặc cả hai đều quá dài. Tên tệp đủ điều kiện phải ít hơn 260 ký tự và tên thư mục phải ít hơn 248 ký tự. tại System.IO.Path.NormalizePathFast (Đường dẫn chuỗi, Boolean fullCheck) tại System.IO.Path.GetFullPathInternal (Đường dẫn chuỗi) tại System.IO.FileStream.Init (Đường dẫn chuỗi, chế độ FileMode, truy cập FileAccess, Quyền Int32, Sử dụng Boolean , Chia sẻ FileShare, Int32 bufferSize, tùy chọn FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) tại System.IO.FileStream..ctor (Đường dẫn chuỗi, Chế độ FileMode, Quyền truy cập FileAccess, Chia sẻ FileShare, Int32 bufferSize, Tùy chọn FileOptions) tại Hệ thống. IO.File.Create (Đường dẫn chuỗi)

nó đạt đến giới hạn cho chuỗi, Mã được đưa ra bên dưới,

#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
Chuyển đổi đường dẫn UNC (hoặc bất cứ thứ gì) thành định dạng 8.3. [Chuyển đổi sang định dạng 8.3 bằng CMD] [1] [1]: stackoverflow.com/questions/10227144/…
AutomationNation,


Có thể trùng lặp. Ở đây tôi đã tìm ra giải pháp stackoverflow.com/a/44211420/5312148
Francesco

Câu trả lời:


58

Vì nguyên nhân của lỗi đã rõ ràng, đây là một số thông tin sẽ giúp bạn giải quyết vấn đề:

Xem bài viết MS này về Đặt tên tệp, đường dẫn và không gian tên

Đây là trích dẫn từ liên kết:

Giới hạn độ dài đường dẫn tối đa Trong Windows API (với một số ngoại lệ được thảo luận trong các đoạn sau), độ dài tối đa cho đường dẫn là MAX_PATH, được định nghĩa là 260 ký tự. Đường dẫn cục bộ được cấu trúc theo thứ tự sau: ký tự ổ đĩa, dấu hai chấm, dấu gạch chéo ngược, tên các thành phần được phân tách bằng dấu gạch chéo ngược và ký tự rỗng kết thúc. Ví dụ: đường dẫn tối đa trên ổ đĩa D là "D: \ một số chuỗi đường dẫn 256 ký tự <NUL>" trong đó "<NUL>" đại diện cho ký tự null kết thúc vô hình cho mã hệ thống hiện tại. (Các ký tự <> được sử dụng ở đây để hiển thị rõ ràng và không thể là một phần của chuỗi đường dẫn hợp lệ.)

Và một số cách giải quyết (lấy từ các bình luận):

Có nhiều cách để giải quyết các vấn đề khác nhau. Ý tưởng cơ bản của các giải pháp được liệt kê dưới đây luôn giống nhau: Giảm độ dài đường dẫn để có path-length + name-length < MAX_PATH. Bạn có thể:

  • Chia sẻ một thư mục con
  • Sử dụng dòng lệnh để gán ký tự ổ đĩa bằng SUBST
  • Sử dụng AddConnection trong VB để gán ký tự ổ đĩa cho một đường dẫn

7
@TimeToThine, bạn đã đọc bài báo mà tôi đăng chưa? Bạn đã đọc các bình luận? Tôi có thể sai, nhưng tôi không nghĩ bạn sẽ nhận được thêm bất kỳ sự trợ giúp nào từ cộng đồng SO, ngoài những gì tôi đã cung cấp.
James Hill

2
Có, tôi đã đọc nó trước khi đăng câu hỏi của mình ở đây, tôi thậm chí đã thử "\\? \" Nhưng vì một số lý do nó không hoạt động trong ngữ cảnh này. Tôi tìm thấy blog này, đang sử dụng nó nhưng vì lý do nào đó mà nó không hoạt động bình thường, " codinghorror.com/blog/2006/08/shortening-long-file-paths.html " Tôi vẫn đang tìm kiếm thứ gì đó giúp lưu thư mục và tôi có thể lấy nó từ đó hoặc tương tự, ví dụ: sử dụng một nhãn ẩn để lưu thư mục hiện tại thay vì chuỗi, nhưng không chắc liệu nó có hoạt động hay không.
Muhammad Raja

24
Đó là điều hiển nhiên nhưng nó không có ý nghĩa gì cả. Tại sao lại có giới hạn về kích thước đường dẫn ??? bây giờ là năm 2017.
Jaider

2
Nếu tôi thay đổi thư mục hiện tại thành thư mục của thư mục sử dụng Directory.SetCurrentDirectory () thì có tránh được hạn chế này không. Hoặc vấn đề sẽ vẫn tồn tại.
Adam Lindsay

3
Có vẻ như bài viết đã được cập nhật: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. Nhưng bạn phải chọn tham gia và đặt khóa đăng ký để kích hoạt nó.
Tom Deblauwe

28

Giải pháp phù hợp với tôi là chỉnh sửa khóa đăng ký để kích hoạt hành vi đường dẫn dài, đặt giá trị thành 1. Đây là tính năng chọn tham gia mới cho Windows 10

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

Tôi nhận được giải pháp này từ một phần có tên của bài viết mà @ james-hill đã đăng.

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


2
Tôi đã đặt giá trị này thành 1 và vẫn gặp lỗi, không hiểu tại sao vào thời điểm này.
Mr Angry

Bài báo đề cập đến hai yêu cầu. Đầu tiên là khóa đăng ký và thứ hai là ứng dụng 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>Đối với tôi trong Visual Studio 2019, yêu cầu thứ hai này không cần thiết sau khi khởi động lại Visual Studio.
Tom Anderson

Tôi xin lỗi có lẽ đây là câu hỏi ngu ngốc nhưng "ứng dụng xml" là gì? Nó là web.config hay cái gì khác? Tôi gặp sự cố này trên dự án Trang web asp.net
Ondra Starenko

Như đã nói ở trên, nó hoạt động tốt trong Visual Studio 2019 (sau khi khởi động lại) mà không thay đổi xml ứng dụng. Cảm ơn vì giải pháp.
Zoman

@TomAnderson: Tôi đang sử dụng VS2017. Tôi có thể tìm thấy application.xml này ở đâu? như sau khi thực hiện bước 1 không giải quyết được vấn đề của tôi.
Sharad


3

Bạn có thể tạo một liên kết tượng trưng với một thư mục ngắn hơn. Mở dòng lệnh đầu tiên, chẳng hạn như Shift + RightClicktrong thư mục mong muốn của bạn với một đường dẫn ngắn hơn (bạn có thể phải chạy nó với tư cách quản trị viên).

Sau đó, nhập với các đường dẫn tương đối hoặc tuyệt đối:

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

Và sau đó bắt đầu Giải pháp từ con đường ngắn hơn. Ưu điểm ở đây là: Bạn không phải di chuyển bất cứ thứ gì.


Điều này không hoạt động trong VS2015. Có vẻ như VS đang xác định trước độ dài của đường dẫn. Xem câu trả lời N-Ate để làm việc xung quanh VS2015.
N-ate

1
Những gì bạn có thể làm là ánh xạ thư mục giải pháp với một trình điều khiển bằng cách sử dụng lệnh "subst". Điều đó hoạt động cho VS2017.
Filipe Calasans

2

Trên Windows 8.1, bằng cách sử dụng. NET 3.5, tôi đã gặp sự cố tương tự.
Mặc dù tên tệp của tôi chỉ có độ dài 239 ký tự khi tôi khởi tạo một đối tượng FileInfo chỉ với tên tệp (không có đường dẫn) đã xảy ra một ngoại lệ thuộc loại Hệ thống. 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

Tôi đã giải quyết sự cố khi cắt tên tệp thành 204 ký tự (bao gồm phần mở rộng).


Thông tin bổ sung cho bất kỳ ai đọc thông tin này - Tên tệp được giới hạn ở 247 ký tự trong khi đường dẫn đầy đủ được giới hạn ở 259. Vì vậy, nếu tên tệp của bạn là 239, thì chỉ để lại 20 ký tự cho phần còn lại của đường dẫn (ví dụ: "c: \ temp") . Nếu bạn cắt tên tệp, bạn cần đảm bảo đường dẫn ĐẦY ĐỦ có 259 ký tự trở xuống.
Losbear 14/1218

1

Nếu bạn đang gặp sự cố với các tệp bin do đường dẫn dài, Trong Visual Studio 2015, bạn có thể truy cập trang thuộc tính của dự án vi phạm và thay đổi Thư mục đầu ra tương đối thành một đường dẫn ngắn hơn.

Ví dụ: bin \ debug \ trở thành C: \ _ bins \ MyProject \


1
Sau khi mở lại thuộc tính khi quá trình xây dựng của tôi bị lỗi, tôi nhận thấy đường dẫn mới "c: \ vs \ bin \ Release" được thay thế bằng ".. \ .. \ .. \ .. \ .. \ .. \ .. \. . \ so với \ bin \ Phát hành \ " . Tôi không chắc liệu ".. \" có được tính vào số ký tự hay không.
samis

2
Đường dẫn được đánh giá là quá dài là đường dẫn tuyệt đối.
N-ate

1

Điều làm việc hiệu quả với tôi là chuyển dự án của tôi như trên màn hình (C: \ Users \ lachezar.l \ Desktop \ MyFolder) sang (C: \ 0 \ MyFolder), như bạn có thể thấy sử dụng đường dẫn ngắn hơn và giảm nó đã giải quyết vấn đề.


1

Từ kinh nghiệm của tôi, tôi sẽ không đề xuất câu trả lời dưới đây cho bất kỳ ứng dụng Web nào.

Nếu bạn cần nó cho các công cụ nội bộ của mình hoặc để Thử nghiệm, tôi khuyên bạn nên chia sẻ nó trên máy của riêng bạn.

-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

Sau đó, điều này sẽ tạo một thư mục được chia sẻ như \\ {PCName} \ {YourSharedRootDirectory} Điều này chắc chắn có thể ít hơn nhiều so với đường dẫn đầy đủ của bạn mà tôi hy vọng, đối với tôi, tôi có thể giảm xuống còn 30 ký tự từ khoảng 290 ký tự. :)


0

Không đề cập đến cho đến nay và một bản cập nhật, có một thư viện thiết lập rất tốt để xử lý các đường dẫn quá dài. AlphaFS là một thư viện .NET cung cấp chức năng hệ thống tệp Win32 hoàn chỉnh hơn cho nền tảng .NET so với các lớp System.IO tiêu chuẩn. Thiếu sót đáng chú ý nhất của .NET System.IO tiêu chuẩn là thiếu hỗ trợ các tính năng NTFS nâng cao, đáng chú ý nhất là hỗ trợ đường dẫn độ dài mở rộng (ví dụ: đường dẫn tệp / thư mục dài hơn 260 ký tự).


0

Câu trả lời tốt nhất mà tôi có thể tìm thấy, nằm trong một trong các bình luận ở đây. Thêm nó vào câu trả lời để ai đó không bỏ lỡ nhận xét và chắc chắn nên thử điều này. Nó đã khắc phục sự cố cho tôi.

Chúng ta cần ánh xạ thư mục giải pháp vào một ổ đĩa bằng lệnh "subst" trong dấu nhắc lệnh - ví dụ: subst z:

Và sau đó mở giải pháp từ ổ đĩa này (z trong trường hợp này). Điều này sẽ rút ngắn đường dẫn nhiều nhất có thể và có thể giải quyết vấn đề tên tệp dài.


0

Điều này cũng có thể là giải pháp. Đôi khi cũng xảy ra khi bạn giữ dự án Phát triển của mình quá sâu, có nghĩa là thư mục dự án có thể có quá nhiều thư mục, vì vậy vui lòng không tạo quá nhiều thư mục, hãy giữ nó trong một thư mục đơn giản bên trong ổ đĩa. Ví dụ- Tôi cũng gặp lỗi này khi dự án của tôi được giữ như thế này-

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

sau đó tôi chỉ cần dán dự án của mình vào bên trong

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication

Và vấn đề đã được giải quyết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.