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

发布于 2024-11-17 19:41:10 字数 1053 浏览 2 评论 0原文

我有一个与 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 件事有点混乱,所以我仍然愿意接受建议。

I have an event receiver tied to a SharePoint 2010 picture library. When a picture is uploaded, I want to open it for processing. Files uploaded with the web interface work fine, but files copied via Windows Explorer view return zero bytes. Simplified code below.

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!
}

If I insert a delay before opening, it works.

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
}

But I though that ItemAdded was only called after everything was done, including file upload.
I also found that file.CanOpenFile(true) always returns true, whether or not OpenBinary works.

How can I make sure the file is ready to open before I call OpenBinary()?
I don't like the Thread.Sleep solution, because I'm sure larger files or a busier server would require more wait. The time required can't be predicted, and I don't want to loop and try again forever.

Update: I originally thought the failure to open was caused by larger files. Question has been updated to reflect the explorer view as the cause. I also find that Windows Explorer copy also triggers ItemUpdated (twice), and I am able to open the file here. A little messy to have 3 triggers, 2 calls to do 1 thing, so I am still open to suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心欲静而疯不止 2024-11-24 19:41:10

我今天刚刚在 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;

              }

        }

I just encountered this issue today on SharePoint 2013. I've taken the suggestions listed here and improved upon them.

It's fine making the thread sleep for 2 seconds, but what happens when you have a large file? You're going to run into the same issue.

My code fix is as follows:

     //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;

              }

        }
乖乖 2024-11-24 19:41:10

我在 SP2010 和 SP2013 中面临同样的问题。知道如何解决这个问题吗?

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

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

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

I face the same Problem within SP2010 and SP2013. Any Idea how to solve this?

Somehow this have something to do with bigger files. Small Files work without any problems, bigger files (400kb) won't work always.

I have only one hint. If you copy & paste a file over windows explorer (WebDAV) to the Library the EventHandle (ItemAdded) will trigger as soon the File was created. But this doesn't mean the File is already filled with data. I saw this once, my debugger hit my breakpoint even while windows was still busy with the copyprocess.

Would be great to know when the copyprocess is finished. I thought i could do this by just do "spfile.openBinary()" and if its empty, just wait 2 sec and do it again until it will get something bigger than 0 bytes. But this doesnt work! It only work if you are waiting BEFORE you call openBinary() the first time, all other times of calling openBinary() lead to the same result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文