我在SharePoint上面临WebDav的问题。我在.NET中创建了一个很好的WebDav库来支持复制和移动文件和文件夹结构,但是我无法解决以下问题。
我正在使用.NET 4.0,连接到SharePoint 2010。
在同一网站集中执行复制时,它可以正常工作:
所以复制
http://my-sps-server/sc1/folder1/file1.txt
到
http://my-sps-server/sc1/folder2/file1.txt
没问题,但是
http://my-sps-server/sc1/folder1/file1.txt
到
http://my-sps-server/sc2/folder2/file1.txt
引发异常,响应状态告诉我,我从服务器返回409。有趣的是,在复制之前我确保文件夹'folder2'存在,如果没有,它就会被创建,并且没有任何问题。但409响应的细节告诉我路径'folder2'不存在。
我一直在研究身份验证,我正在使用网络默认凭据,可以在同一个sitecollection中复制以及创建文件夹时正常工作。还使用fiddler模拟http请求,给出了相同的409响应,因此很可能不是.NET代码。
我想知道SharePoint 2010中是否存在任何错误。
希望有人可以在这里发光或给我一些指示?
结束从源代码执行下载并上传到目标(在内存中),代码:
private byte[] DownloadFile(Uri uri)
{
var request = GetRequest(uri);
request.Method = "GET";
request.Headers.Add("Translate", "f");
var response = request.GetResponse();
using (var stream = response.GetResponseStream())
{
return ReadFileBytes(stream, (int)response.ContentLength);
}
}
private void UploadFile(Uri uri, byte[] bytes)
{
var request = GetRequest(uri);
request.Method = "PUT";
request.ContentLength = bytes.Length;
request.Headers.Add("Translate", "f");
using (var stream = request.GetRequestStream())
{
stream.Write(bytes, 0, bytes.Length);
stream.Close();
}
request.GetResponse();
}
/// <summary>
/// Reads data from a stream until the end is reached. The
/// data is returned as a byte array. An IOException is
/// thrown if any of the underlying IO calls fail.
/// </summary>
/// <param name="stream">The stream to read data from</param>
/// <param name="initialLength">The initial buffer length</param>
private static byte[] ReadFileBytes(Stream stream, int initialLength)
{
// If we've been passed an unhelpful initial length, just
// use 32K.
if (initialLength < 1)
{
initialLength = 32768;
}
byte[] buffer = new byte[initialLength];
int read = 0;
int chunk;
while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
{
read += chunk;
// If we've reached the end of our buffer, check to see if there's
// any more information
if (read == buffer.Length)
{
int nextByte = stream.ReadByte();
// End of stream? If so, we're done
if (nextByte == -1)
{
return buffer;
}
// Nope. Resize the buffer, put in the byte we've just
// read, and continue
byte[] newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[read] = (byte)nextByte;
buffer = newBuffer;
read++;
}
}
// Buffer is now too big. Shrink it.
byte[] ret = new byte[read];
Array.Copy(buffer, ret, read);
return ret;
}
请注意,下载和上传会降低性能,这对于使用大型文件执行此操作时可能会非常明显。
您可以像这样执行整个复制操作:
UploadFile(to,DownloadFile(from));
答案 0 :(得分:0)
我们最近花了相当多的时间来尝试解决这个问题,但遗憾的是没有得到任何结果。关于这个主题有很多旧的StackExchange帖子,结果大致相同 - 没有人真正理解导致这种冲突的原因,似乎没有人能够正确解决它。我可以告诉你的是,你似乎还没有发现,如果你创建新的文档库来在两者之间移动文件,这种情况往往不会发生。这表明某种腐败会导致问题。
我们所做的以及可能对您有用的是放弃并使用SharePoint对象模型进行处理。我为此写的课程如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Diagnostics;
// todo: Lists
// DeleteListItem
// WriteFileMetadata
// AddListEntry
// Throttling on copy methods
namespace RE.SharePoint
{
/// <summary>
/// Class to encapsulate methods that interact with SharePoint Lists and Libraries
/// </summary>
public class ListsAndItems
{
/// <summary>
/// Move items from a list to another list in the same site
/// </summary>
/// <param name="siteURL">URL to the host site collection</param>
/// <param name="sourceList">URL to the source list</param>
/// <param name="destinationList">URL to the destination list</param>
/// <param name="retainMeta">Option to retain meta data (created/modified dates) or create new ones</param>
/// <returns>Boolean value, true for successful copy, false for a failed copy</returns>
public bool MoveListItems(string siteURL, string sourceList, string destinationList, bool retainMeta)
{
OnSharePointOpeningSite(siteURL);
using (var site = new SPSite(siteURL))
{
OnSharePointOpenedSite(siteURL);
using (var web = site.OpenWeb())
{
OnSharePointGetRelativeURL(web.ServerRelativeUrl);
try
{
// Get your source and destination libraries
var source = web.GetList(web.ServerRelativeUrl + sourceList);
var destination = web.GetList(web.ServerRelativeUrl + destinationList);
OnSharePointSourceSet(source);
OnSharePointDestinationSet(destination);
// Get the collection of items to move, use source.GetItems(SPQuery) if you want a subset
SPListItemCollection items = source.Items;
// Get the root folder of the destination we'll use this to add the files
SPFolder folder = web.GetFolder(destination.RootFolder.Url);
OnSharePointProcessItem(items.Count, source.ToString(), destination.ToString());
var fileCount = 0;
// Now to move the files and the metadata
foreach (SPListItem item in items)
{
//Get the file associated with the item
SPFile file = item.File;
OnSharePointProcessFile(folder.Url + "/" + file.Name);
// Create a new file in the destination library with the same properties
SPFile newFile = folder.Files.Add(folder.Url + "/" + file.Name, file.OpenBinary(), file.Properties, true);
if (retainMeta)
{
SPListItem newItem = newFile.Item;
WriteFileMetaDataFiletoFile(item, newItem);
}
file.Delete();
SharePointRecycleBin.EmptyRecycleBinItem(site.ToString(), source.ToString(), file.Name);
fileCount++;
}
OnSharePointProcessList(fileCount, source.ToString(), destination.ToString());
}
catch (System.IO.FileNotFoundException fex)
{
OnError("Unable to set a location. Please check that paths for source and destination libraries are correct and relative to the site collection. \n\nSite URL: "
+ siteURL + " \nSource List: " + sourceList + " \nDestination List: " + destinationList + "\n", false, fex);
return false;
}
catch (Exception ex)
{
OnError("General Exception: ", true, ex);
return false;
}
return true;
}
}
}
/// <summary>
/// Move items from one SharePoint list to another in another site
/// </summary>
/// <param name="sourceSiteURL">The URL to the source site collection</param>
/// <param name="sourceList">The URL to the source list</param>
/// <param name="destinationSiteURL">The URL to the destination site collection</param>
/// <param name="destinationList">The URL to the destination list</param>
/// <param name="retainMeta">Option to retain meta data (created/modified dates) or create new ones</param>
/// <returns>Boolean value, true for successful copy, false for a failed copy</returns>
public bool MoveListItemsSiteToSite(string sourceSiteURL, string sourceList, string destinationSiteURL, string destinationList, bool retainMeta)
{
OnSharePointOpeningSite(sourceSiteURL);
using (SPSite sourceSite = new SPSite(sourceSiteURL))
{
OnSharePointOpenedSite(sourceSiteURL);
using (SPWeb sourceWeb = sourceSite.OpenWeb())
{
OnSharePointGetRelativeURL(sourceWeb.ServerRelativeUrl);
try
{
// Get your source library
var source = sourceWeb.GetList(sourceWeb.ServerRelativeUrl + sourceList);
OnSharePointSourceSet(source);
// Get the collection of items to move, use source.GetItems(SPQuery) if you want a subset
SPListItemCollection items = source.Items;
int fileCount = 0;
OnSharePointOpeningSite(destinationSiteURL);
using (var destSite = new SPSite(destinationSiteURL))
{
OnSharePointOpenedSite(destinationSiteURL);
using (var destinationWeb = destSite.OpenWeb())
{
OnSharePointGetRelativeURL(destinationWeb.ServerRelativeUrl);
// get destination library
SPList destination = destinationWeb.GetList(destinationWeb.ServerRelativeUrl + destinationList);
OnSharePointDestinationSet(destination);
// Get the root folder of the destination we'll use this to add the files
SPFolder destinationFolder = destinationWeb.GetFolder(destination.RootFolder.Url);
OnSharePointProcessItem(items.Count, source.ToString(), destination.ToString());
// Now to move the files and the metadata
foreach (SPListItem item in items)
{
//Get the file associated with the item
SPFile file = item.File;
// Add event handler
OnSharePointProcessFile(destinationFolder.Url + "/" + file.Name);
// Create a new file in the destination library with the same properties
SPFile newFile = destinationFolder.Files.Add(destinationFolder.Url + "/" + file.Name, file.OpenBinary(),
file.Properties, true);
if (retainMeta)
{
SPListItem newItem = newFile.Item;
WriteFileMetaDataFiletoFile(item, newItem);
}
file.Delete();
SharePointRecycleBin.EmptyRecycleBinItem(sourceSite.ToString(), source.ToString(), file.Name);
fileCount++;
}
OnSharePointProcessList(fileCount, source.ToString(), destination.ToString());
}
}
}
catch (System.IO.FileNotFoundException fex)
{
OnError("Unable to set a location. Please check that paths for source and destination libraries are correct and relative to the site collection. \n\nSource Site: "
+ sourceSiteURL + " \nSource List: " + sourceList + " \nDestination Site: " + destinationSiteURL + " \nDestination List: " + destinationList + "\n", false, fex);
return false;
}
catch (Exception ex)
{
OnError("General Exception: ", true, ex);
return false;
}
return true;
}
}
}
/// <summary>
/// overwrites a list items meta data with meta data from another file
/// </summary>
/// <param name="sourceItem">The source item to take meta data from</param>
/// <param name="destinationItem">The destination item to set meta data from the source item to</param>
public static void WriteFileMetaDataFiletoFile(SPListItem sourceItem, SPListItem destinationItem)
{
destinationItem["Editor"] = sourceItem["Editor"];
destinationItem["Modified"] = sourceItem["Modified"];
destinationItem["Modified By"] = sourceItem["Modified By"];
destinationItem["Author"] = sourceItem["Author"];
destinationItem["Created"] = sourceItem["Created"];
destinationItem["Created By"] = sourceItem["Created By"];
destinationItem.UpdateOverwriteVersion();
}
#region Events
internal void OnSharePointProcessFile(string itemPath)
{
if (_sharePointProcessedFile == null) return;
var e = new SharePointProcessFileEventArgs(itemPath);
_sharePointProcessedFile(this, e);
}
internal void OnSharePointProcessItem(int itemCount, string source, string destination)
{
if (_sharePointProcessItem == null) return;
var e = new SharePointProcessItemEventArgs(itemCount, source, destination);
_sharePointProcessItem(this, e);
}
internal void OnSharePointProcessList(int itemCount, string source, string destination)
{
if (_sharePointProcessList == null) return;
var e = new SharePointProcessListEventArgs(itemCount, source, destination);
_sharePointProcessList(this, e);
}
internal void OnSharePointOpeningSite(string siteName)
{
if (_sharePointOpeningSite == null) return;
var e = new SharePointOpeningSiteEventArgs(siteName);
_sharePointOpeningSite(this, e);
}
internal void OnSharePointOpenedSite(string siteName)
{
if (_sharePointOpenedSite == null) return;
var e = new SharePointOpenedSiteEventArgs(siteName);
_sharePointOpenedSite(this, e);
}
internal void OnSharePointGetRelativeURL(string siteCollection)
{
if (_sharePointRelativeURL == null) return;
var e = new SharePointWebRelativeURLEventArgs(siteCollection);
_sharePointRelativeURL(this, e);
}
internal void OnSharePointDestinationSet(SPList destination)
{
if (_sharepointDestination == null) return;
var e = new SharePointDestinationSetEventArgs(destination);
_sharepointDestination(this, e);
}
internal void OnSharePointSourceSet(SPList source)
{
if (_sharepointSource == null) return;
var e = new SharePointSourceSetEventArgs(source);
_sharepointSource(this, e);
}
internal void OnError(string message, bool showException, Exception exception)
{
if (_sharePointOnError == null) return;
var e = new SharePointOnErrorEventsArgs(message, showException, exception);
_sharePointOnError(this, e);
}
private EventHandler<SharePointProcessFileEventArgs> _sharePointProcessedFile;
private EventHandler<SharePointProcessListEventArgs> _sharePointProcessList;
private EventHandler<SharePointOpeningSiteEventArgs> _sharePointOpeningSite;
private EventHandler<SharePointOpenedSiteEventArgs> _sharePointOpenedSite;
private EventHandler<SharePointWebRelativeURLEventArgs> _sharePointRelativeURL;
private EventHandler<SharePointDestinationSetEventArgs> _sharepointDestination;
private EventHandler<SharePointSourceSetEventArgs> _sharepointSource;
private EventHandler<SharePointProcessItemEventArgs> _sharePointProcessItem;
private EventHandler<SharePointOnErrorEventsArgs> _sharePointOnError;
/// <summary>
/// Event for handling exceptions
/// </summary>
public event EventHandler<SharePointOnErrorEventsArgs> SharePointOnError
{
add { _sharePointOnError += value; }
remove { _sharePointOnError += value; }
}
/// <summary>
/// Event for when a file is being processed
/// </summary>
public event EventHandler<SharePointProcessFileEventArgs> SharePointProcessFile
{
add { _sharePointProcessedFile += value; }
remove { _sharePointProcessedFile += value; }
}
/// <summary>
/// Event for when a site is attempting to open
/// </summary>
public event EventHandler<SharePointOpeningSiteEventArgs> SharePointOpeningSite
{
add { _sharePointOpeningSite += value; }
remove { _sharePointOpeningSite -= value; }
}
/// <summary>
/// Event for when a site has been successfully opened
/// </summary>
public event EventHandler<SharePointOpenedSiteEventArgs> SharePointOpenedSite
{
add { _sharePointOpenedSite += value; }
remove { _sharePointOpenedSite -= value; }
}
/// <summary>
/// Event for when source/destination and filecount are established and a copy is about to initiate
/// </summary>
public event EventHandler<SharePointProcessItemEventArgs> SharePointProcessItem
{
add { _sharePointProcessItem += value; }
remove { _sharePointProcessItem -= value; }
}
/// <summary>
/// Event for when a list has started processing
/// </summary>
public event EventHandler<SharePointProcessListEventArgs> SharePointProcessList
{
add { _sharePointProcessList += value; }
remove { _sharePointProcessList -= value; }
}
/// <summary>
/// Event for when a web relative URL has been retreived from the site collection name
/// </summary>
public event EventHandler<SharePointWebRelativeURLEventArgs> SharePointWebRelativeURL
{
add { _sharePointRelativeURL += value; }
remove { _sharePointRelativeURL -= value; }
}
/// <summary>
/// Event for when a destination location has been assigned
/// </summary>
public event EventHandler<SharePointDestinationSetEventArgs> SharePointDestinationSet
{
add { _sharepointDestination += value; }
remove { _sharepointDestination -= value; }
}
/// <summary>
/// Event for when a source location has been assigned
/// </summary>
public event EventHandler<SharePointSourceSetEventArgs> SharePointSourceSet
{
add { _sharepointSource += value; }
remove { _sharepointSource -= value; }
}
#endregion
}
}
一旦该选项可用,我也会为你提供这个帖子...希望现在已经过了足够的时间,以便社区中的某些人知道如何解决这个问题。