自定义文件属性

13

我需要以下内容:

在我的应用程序中,我有一些文件需要不断地签入和签出。当我从应用程序中签出一个文件时,我需要向该文件添加自定义属性,以便在以后签入该文件时能够识别它。

我尝试使用DSOFile的OleDocumentProperties来实现这个目标,但是没有成功。以下是我尝试过的代码:

 // Adding custom properties to file (Parameters: FileName, custom property name, value, debug: true/false
 DocumentProperties.WriteDocumentProperty(filename, "dms_dossiernummer", _dossiernummer.ToString(), false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_zaaknaam", ReturnZaaknaam(_dossiernummer), false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_verantw_medew", ReturnVerantwMedew(_dossiernummer), false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_document_path", path, false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_bestandsnaam", bestandsNaam, false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_bestands_id", bestandId, false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_is_checkedout", "true", false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_dossier_map_id", dossierMapId, false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_bestand_versie_nummer", Queries.Dms.Selects.GetDocumentVersion(
                                                        Convert.ToInt32(bestandId)).ToString(), false);
 DocumentProperties.WriteDocumentProperty(filename, "dms_bestands_locatie", path, false);

有没有人知道如何为文件添加自定义文件属性的其他方法?


1
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
SharePoint Foundation是SharePoint免费版本的新名称。它具有广泛的API。您可以将文档存储在SP文档库中,甚至带有自定义元数据,如果您愿意,您永远不需要向用户展示SP用户界面。真的,它是免费的。了解一下吧。 - John Saunders
由你决定,但如果有一个管理文档的代码库,那么我敢打赌你可以使用它。把SP想象成一个恰好存在于Web服务器上的库。用户永远不需要“看到”SP。 - John Saunders
2
大多数Win32 API可以从C#中调用,只是需要更多的工作。阅读他链接的文章,然后了解“P/Invoke”。 - John Saunders
2
为什么不在结帐时向结帐目录添加一个文件,其中包含该路径中所有项目的元数据?就像SVN一样。就像Olly下面最后一个小圆点所说的那样:D - Paul Zahra
显示剩余13条评论
4个回答

15

什么是文件?

在本质上,文件只是一串字节和文件系统关联的一些元数据。在早期的文件系统中,元数据基本上只有文件名和一些日期戳。像NTFS这样的新型文件系统可以选择添加额外的元数据。

文档属性来自哪里?

在Windows资源管理器中,您可以看到许多文件类型的文档属性。美观且统一的界面表明存在某种统一的属性存储库。但实际上并非如此。资源管理器Shell具有可扩展的接口,用于从各种文件类型中提取此信息的属性表处理程序。对于JFIF(JPEG)文件,有一个处理程序,还有适用于OLE文件(旧版Office格式)和新的Office格式的处理程序。

我应该将元数据放在哪里?

结论是:

  • 如果您能够保证只需要处理特定的文件格式,请尝试在文件内部添加元数据。例如:

    • 如果所有文件都是旧版Office文档(.doc),则使用OLE属性

    • 如果所有文档都是新式Office文档(.docx),则使用Open XML API

  • 如果您能够保证所有安装都在特定的文件系统上,请研究文件系统的功能。其他回答已经考虑了如何在NTFS上实现此目标。

  • 否则,您必须设计自己的数据存储方式。 同伴文件是一个明显的可能性; 您可以将元数据存储在数据库中; 或者您可以创建一个文件夹对应一个文件来保存该目录中文件的所有元数据。请考虑是否可能面临多个请求同一文件的并发问题。使用数据库可能使处理这些问题更加简单明了。


  • 我需要创建一个库,用于存储媒体文件(视频、音频、文档)的信息。MD是一个包含许多细节的自定义结构,我希望将其全部存储在文件本身中,并拥有一个客户端应用程序,能够分析MD并显示或通过它进行搜索。 我的问题在于外部文件或数据库中的文件被删除时会发生什么。 所以我的简单问题是,如果我不介意坚持使用NTFS,我可以将任何元数据存储到NTFS中的任何文件吗?另一个问题是,当文件被复制到兼容系统时,Windows是否会保留MD,或者至少在复制之前警告即将丢失的MD。 - Shimmy Weitzhandler
    1
    @Shimmy,看起来Brad在下面的回答中提供的这篇文章链接几乎就是你需要的,尽管在复制到非NTFS卷时,Windows似乎不会警告你会丢失额外的信息。 - Olly

    7

    备用数据流将允许您存储任何数据。请注意:如果将文件复制到非NTFS文件系统,则会剥离额外的数据。

    这里是一篇文章,应该可以帮助您入门

    -- 编辑于1/2/2014 --
    以下是更多信息: http://www.codeproject.com/Articles/2670/Accessing-alternative-data-streams-of-files-on-an http://www.dreamincode.net/forums/topic/90666-reading-and-writing-alternate-streams-in-c%23/ NTFS备用数据流-.NET

    还有一个用于在命令行中创建/查看广告的工具: http://www.undermyhat.org/blog/2012/05/copy-delete-or-rename-alternate-data-streams-using-only-standard-windows-command-prompt-tools/


    3
    尽管可以使用DSOFile.dll打开任何类型的文件,但是除了OLE结构化存储/Ole文档(如旧版Microsoft Office文件(.doc、.xls等)和一些CAD文件)之外,自定义属性将不会被持久化。正如Brad所写,您可以选择备用数据流,但这也有一个依赖项,即NTFS文件系统。我不建议您采用这些方法...如果您使用一个新文件,比如.props或类似的东西,会怎样呢?

    2

    这里有多个选择。

    如上所述,如果您可以保证文件始终位于NTFS上,备用数据流是一个不错的选择。

    您可以将自定义属性编写为JSON、XML、序列化对象或甚至是简单的行+分隔符格式。

    不幸的是,这些选项在使用.NET时并不完全可用,您需要使用P/Invoke和CreateFile。

    [DllImport( "kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true )]
        private static extern SafeFileHandle CreateFile(
              string lpFileName,
              uint dwDesiredAccess,
              uint dwShareMode,
              IntPtr SecurityAttributes,
              uint dwCreationDisposition,
              uint dwFlagsAndAttributes,
              IntPtr hTemplateFile
              );
    

    你需要使用文件路径创建数据流,然后在文件名后面加上冒号和流的名称,并将CreateFile返回的SafeFileHandle传递给FileStream的构造函数。通过此API打开文件的其他选项与正常情况下相同。
    请注意,如果要写入到替代数据流中,必须对文件具有写访问权限。
    以下是CreateFile的参考文献:http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx 以下是一些有用的常量:
        private  const    uint     GENERIC_WRITE                 = 0x40000000;
        private  const    uint     GENERIC_READ                  = 0x80000000;
    
        private  const    uint     FILE_SHARE_READ               = 0x00000001;
        private  const    uint     FILE_SHARE_WRITE              = 0x00000002;
    
        private  const    uint     CREATE_NEW                    = 1;
        private  const    uint     CREATE_ALWAYS                 = 2;
        private  const    uint     OPEN_EXISTING                 = 3;
        private  const    uint     OPEN_ALWAYS                   = 4;
    

    一种不需要P/Invoke并且友好于除NTFS外的其他文件系统的方法是创建第二个文件,将原始文件的完整路径名添加另一个扩展名。同样,您可以使用首选的存储属性的方法来存储此文件中的属性。但是,这种方法的缺点是如果用户移动文件,则必须同时移动属性。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接