SharePoint ItemAdded和SPFile.OpenBinary(),零字节

时间:2011-06-30 00:02:08

标签: sharepoint sharepoint-2010 event-receiver

我有一个绑定到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件事,所以我仍然愿意接受建议。

2 个答案:

答案 0 :(得分: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;

              }

        }

答案 1 :(得分:0)

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

不知何故,这与更大的文件有关。小文件没有任何问题,较大的文件(400kb)将无法正常工作。

我只有一个提示。如果你复制&将文件通过Windows资源管理器(WebDAV)粘贴到库中,EventHandle(ItemAdded)将在创建文件后立即触发。但这并不意味着文件已经填满了数据。我曾经看过这个,我的调试器即使在窗口仍然忙于copyprocess的情况下也能达到我的断点。

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