Проверьте, защищен ли файл Excel паролем в.NET Core

Технология:

C#

ASP.NET Core 2.0

Excel (в основном OpenXml, но иногда устаревший документ)

В настоящее время используется ExcelDataReader для чтения файлов.

Сценарий:

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

Некоторые пользователи защищают свои файлы Excel паролем, и требуется, чтобы эти файлы оставались защищенными паролем на сервере.

Проблема:

Мне нужно определить, защищен ли документ паролем, чтобы я мог использовать соответствующую конфигурацию для доступа к нему.

Я немного погуглил, но в основном это Workbook.HasPassword (я думаю, что это часть Excel.Interop, которую я бы не хотел добавлять). Я также нашел эту ссылку на аналогичный вопрос в документах Office, в котором решением был длинный контрольный список для различных данных заголовка через файловый поток.

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

Какие-либо предложения?

3 ответа

Решение

Поскольку вы уже используете ExcelDataReader, откройте файл в предложении try-catch и обработайте его. InvalidPasswordException:

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

Это не слишком плохая производительность. За кулисами он проверяет только соответствующие заголовки в файле и обрабатывает все подробности BIFF, ZIP и версий. Данные не будут прочитаны, если нет пароля.

Вы не узнаете, защищен ли файл паролем, не открывая файл. Эта информация находится в файле (насколько я знаю); это не выставлено в файловой системе.

Вы должны быть в состоянии быстро добиться этого, используя OpenXml SDK. Создайте незащищенный файл. Скопируйте это. Откройте копию, установите пароль и сохраните его. Затем используйте openXml "Productivity Tool", чтобы различать два файла ("Compare Files", вверх на панели инструментов). Это должно быстро сосредоточиться на том, где искать.

Это старый пост, который я добавляю к нему, но недавно я хотел установить, защищены ли электронные таблицы паролем на C# без использования внешней библиотеки. В итоге я создал следующий код.

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

ПРИМЕЧАНИЕ . Количество пробелов в сравнительном тексте важно, поэтому будьте осторожны при вырезании и вставке.

      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);
}
Другие вопросы по тегам