1

我有一个绑定到 SharePoint 2010 图片库的事件接收器。上传图片后,我想打开它进行处理。使用 Web 界面上传的文件工作正常,但通过 Windows 资源管理器视图复制的文件返回零字节。下面的简化代码。

public override void ItemAdded(SPItemEventProperties properties)
{
    SPListItem item = properties.ListItem;
    SPFile file = item.File;
    byte[] buffer = file.OpenBinary(); //buffer has zero bytes for files copied in Windows Explorer!
}

如果我在打开之前插入延迟,它会起作用。

public override void ItemAdded(SPItemEventProperties properties)
{
    SPListItem item = properties.ListItem;
    SPFile file = item.File;
    System.Threading.Thread.Sleep(2000);
    byte[] buffer = file.OpenBinary(); //buffer now populated correctly
}

但我认为 ItemAdded 仅在一切完成后才被调用,包括文件上传。我还发现 file.CanOpenFile(true) 总是返回 true,无论 OpenBinary 是否有效。

在调用 OpenBinary() 之前,如何确保文件已准备好打开?我不喜欢 Thread.Sleep 解决方案,因为我确信更大的文件或更繁忙的服务器需要更多的等待。所需的时间无法预测,我不想永远循环再试一次。

更新:我原本以为打开失败是因为文件比较大。问题已更新,以反映资源管理器的观点作为原因。我还发现 Windows 资源管理器副本也会触发 ItemUpdated(两次),我可以在此处打开文件。有 3 个触发器,2 个调用做 1 件事有点混乱,所以我仍然愿意接受建议。

4

2 回答 2

2

我今天刚刚在 SharePoint 2013 上遇到了这个问题。我采纳了此处列出的建议并对其进行了改进。

让线程休眠 2 秒很好,但是当你有一个大文件时会发生什么?你会遇到同样的问题。

我的代码修复如下:

     //Check if the SPContext is null since Explorer View isn't within the context
     if (SPContext.Current == null)
        {
          //If the initial file length is 0, pause the thread for 2 seconds
          if (properties.ListItem.File.Length == 0)
             {

               System.Threading.Thread.Sleep(2000);

               //Since our item exists, run the GetItemById to instantiate a new  and updated SPListItem object 
               var spFile = properties.List.GetItemById(properties.ListItemId);

               //SharePoint places an Exclusive lock on the file while the data is being loaded into the file
               while (spFile.File.LockType != SPFile.SPLockType.None)
                     {
                       System.Threading.Thread.Sleep(2000);
                       spFile = properties.List.GetItemById(properties.ListItemId);

                       //We need to check if the file exists, otherwise it will loop forever if someone decides to cancel the upload
                       if (!spFile.File.Exists)
                        return;
                     }

                //If someone thought it was a good idea to actually load a 0 byte file, don't do anything else
                if (spFile.File.Length == 0)
                       return;

              }

        }
于 2014-05-23T15:45:15.983 回答
0

我在 SP2010 和 SP2013 中面临同样的问题。任何想法如何解决这个问题?

不知何故,这与更大的文件有关。小文件没有任何问题,大文件(400kb)并不总是有效。

我只有一个提示。如果您通过 Windows 资源管理器 (WebDAV) 将文件复制并粘贴到库中,则 EventHandle (ItemAdded) 将在文件创建后立即触发。但这并不意味着文件已经充满了数据。我看到过一次,即使 Windows 仍在忙于复制过程,我的调试器也命中了我的断点。

很高兴知道复制过程何时完成。我想我可以通过只做“spfile.openBinary()”来做到这一点,如果它是空的,只需等待 2 秒,然后再做一次,直到它得到大于 0 字节的东西。但这不起作用!仅当您在第一次调用 openBinary() 之前等待时才有效,所有其他调用 openBinary() 都会导致相同的结果。

于 2013-03-28T13:18:13.780 回答