简体   繁体   中英

Check whether Excel file is password protected in .NET Core

Tech:

C#

ASP.NET Core 2.0

Excel (Mostly OpenXml, but occasional legacy document)

Currently using ExcelDataReader to read the files.

Scenario:

I need to store some files on a server and access them later to do work. Users upload the files through a web API and make calls requesting work to be done in the same way.

Some of the users password-protect their Excel files, and it is a requirement that these files remain password-protected while on the server.

Problem:

I need to detect whether the document is password-protected so I can use the appropriate configuration to access it.

I've googled this a good bit, but it mostly comes up with Workbook.HasPassword (I think this is part of Excel.Interop, which I'd like to avoid adding). I also found this link to a similar question on Office documents, in which the solution was a long checklist against various header data via file stream.

Ideally, I'd like a Core-friendly solution that does not require me to open the file. I don't work with documents that often so I'm at a loss as to where to look next.

Any suggestions?

Since you are already using ExcelDataReader, open the file in a try-catch clause and handle InvalidPasswordException :

bool ExcelFileRequiresPassword(Stream stream) {
    try {
        using (ExcelReaderFactory.CreateReader(stream)) { }
    } catch (InvalidPasswordException) {
        return true;
    }
    return false;
}

This is not too bad performance wise. Behind the scenes it checks only the relevant headers in the file, and handles all the gory BIFF, ZIP and versioning details. No data will be read if there is no password.

You aren't going to find out whether the file is password protected without opening the file. That information is in the file (as far as I know); it's not exposed in the file system.

You should be able to get at it quickly using the OpenXml SDK. Create a non-protected file. Copy it. Open the copy and set a password and save it. Then use the openXml "Productivity Tool" to diff the two files ("Compare Files", up on the tool bar). It should zero in quickly on where to look.

This is an old post as I add to it, but recently I wanted to establish if spreadsheets were password protected in C# without using an external library I ended up creating the following code.

There may be cases and file formats that I have not found, but this will I hope put you on the right track.

NOTE: The number of spaces in the comparison text, is important so be careful when cutting and pasting.

static bool IsExcelPasswordProtected(string strSource)
{
    bool blResult = false;

    if (File.Exists(strSource))
    {
        char[] chBuffer = new char[4096];   // The character strings usually occur within the first 2K in my testing, but just in case
        TextReader trReader = new StreamReader(strSource, Encoding.UTF8, true);

        // Read the buffer
        trReader.ReadBlock(chBuffer, 0, chBuffer.Length);
        trReader.Close();

        // Remove non-printable and unicode characters, we're only interested in ASCII character set
        for (int i = 0; i < chBuffer.Length; i++)
        {
            if ((chBuffer[i] < ' ') || (chBuffer[i] > '~')) chBuffer[i] = ' ';
        }

        string strBuffer = new string(chBuffer);

        // .xls format files, version 97 to 2003 contains this text when password protected
        if (strBuffer.Contains("M i c r o s o f t   E n h a n c e d   C r y p t o g r a p h i c   P r o v i d e r"))
        {
            blResult = true;
        }
        // .xlsx format files contain this text when password protected
        else if (strBuffer.Contains("E n c r y p t e d P a c k a g e"))
        {
            blResult = true;
        }
        // .xlsx format files contain this text when not password protected
        else if (strBuffer.Contains("[Content_Types]"))
        {
            blResult = false;
        }
        // .xlsx format files contain this text when not password protected
        else
        {
            blResult = false;
        }
    }
    else
    {
        // File not found...deal with as you wish
    }

    return (blResult);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM