1

我正在使用 CSOM 将文件上传到 Sharepoint 365 站点。

我已经使用此处找到的方法使用基于声明的身份验证成功登录“ http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx "

但是在 ClientContext 上使用 SaveBinaryDirect 失败并出现 405,因为 cookie 附加到请求太晚了。

使用 CSOM 上传文件的另一种方法与以下类似。但是对于 SP 365,这将文件大小限制为大约 3 兆。

 var newFileFromComputer = new FileCreationInformation
                {
                    Content = fileContents,
                    Url = Path.GetFileName(sourceUrl)
                };


 Microsoft.SharePoint.Client.File uploadedFile = customerFolder.Files.Add(newFileFromComputer);
                    context.Load(uploadedFile);
                    context.ExecuteQuery();

有什么方法可以使用 CSOM、SP 365 和最大 100 兆的文件大小来做到这一点?

4

2 回答 2

1

好吧,我还没有找到使用 CSOM 的方法,这真是令人愤怒。

SEvans 在http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx的评论中发布了一个解决方法。

基本上只需做一个 http put 并附加来自基于声明的身份验证的 cookie 集合。SEvans 发布的解决方法如下


很棒的代码 Wichtor。正如其他人所指出的,SaveBinaryDirect 无法正常工作,因为 FedAuth cookie 永远不会附加到该方法生成的 HTTP PUT 请求。

这是我的解决方法:

// "url" is the full destination path (including filename, i.e. https://mysite.sharepoint.com/Documents/Test.txt) 

// "cookie" is the CookieContainer generated from Wichtor's code 
// "data" is the byte array containing the files contents (used a FileStream to load) 

System.Net.ServicePointManager.Expect100Continue = false; 
HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; 
request.Method = "PUT"; 
request.Accept = "*/*"; 
request.ContentType = "multipart/form-data; charset=utf-8"; 
request.CookieContainer = cookie; request.AllowAutoRedirect = false; 
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; 
request.Headers.Add("Accept-Language", "en-us"); 
request.Headers.Add("Translate", "F"); request.Headers.Add("Cache-Control", "no-cache"); request.ContentLength = data.Length; 

using (Stream req = request.GetRequestStream()) 
{ req.Write(data, 0, data.Length); } 

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
Stream res = response.GetResponseStream(); 
StreamReader rdr = new StreamReader(res); 
string rawResponse = rdr.ReadToEnd(); 
response.Close();
rdr.Close();
于 2013-02-27T14:36:49.340 回答
1

实际上,在尝试在 SharePoint Online 中上传大小超过250MB文件限制的文件时,会发生以下异常:

收到的响应为 -1,Microsoft.SharePoint.Client.InvalidClientQueryException 请求消息太大。服务器不允许大于 262144000 字节的消息。

为了规避这个错误,我们引入了分块文件上传方法,支持上传大于 250 MB 的文件。在提供的链接中,有一个示例演示了如何通过 SharePoint CSOM API 使用它。

支持的版本:

  • SharePoint Online
  • SharePoint On-Premise 2016或更高版本

以下示例演示了如何在 SharePoint REST API 中使用分块文件上传方法:

class FileUploader
{
    public static void ChunkedFileUpload(string webUrl, ICredentials credentials, string sourcePath, string targetFolderUrl, int chunkSizeBytes, Action<long, long> chunkUploaded)
    {
        using (var client = new WebClient())
        {
            client.BaseAddress = webUrl;
            client.Credentials = credentials;
            client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
            var formDigest = RequestFormDigest(webUrl, credentials);
            client.Headers.Add("X-RequestDigest", formDigest);

            //create an empty file first
            var fileName = System.IO.Path.GetFileName(sourcePath);
            var createFileRequestUrl = string.Format("/_api/web/getfolderbyserverrelativeurl('{0}')/files/add(url='{1}',overwrite=true)", targetFolderUrl, fileName);
            client.UploadString(createFileRequestUrl, "POST");

            var targetUrl = System.IO.Path.Combine(targetFolderUrl, fileName);
            var firstChunk = true;
            var uploadId = Guid.NewGuid();
            var offset = 0L;

            using (var inputStream = System.IO.File.OpenRead(sourcePath))
            {
                var buffer = new byte[chunkSizeBytes];
                int bytesRead;
                while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    if (firstChunk)
                    {
                        var endpointUrl = string.Format("/_api/web/getfilebyserverrelativeurl('{0}')/startupload(uploadId=guid'{1}')", targetUrl, uploadId);
                        client.UploadData(endpointUrl, buffer);
                        firstChunk = false;
                    }
                    else if (inputStream.Position == inputStream.Length)
                    {
                        var endpointUrl = string.Format("/_api/web/getfilebyserverrelativeurl('{0}')/finishupload(uploadId=guid'{1}',fileOffset={2})", targetUrl, uploadId, offset);
                        var finalBuffer = new byte[bytesRead];
                        Array.Copy(buffer, finalBuffer, finalBuffer.Length);
                        client.UploadData(endpointUrl, finalBuffer);
                    }
                    else
                    {
                        var endpointUrl = string.Format("/_api/web/getfilebyserverrelativeurl('{0}')/continueupload(uploadId=guid'{1}',fileOffset={2})", targetUrl, uploadId, offset);
                        client.UploadData(endpointUrl, buffer);
                    }
                    offset += bytesRead;
                    chunkUploaded(offset, inputStream.Length);
                }
            }
        }
    }

    public static string RequestFormDigest(string webUrl, ICredentials credentials)
    {
        using (var client = new WebClient())
        {
            client.BaseAddress = webUrl;
            client.Credentials = credentials;
            client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
            client.Headers.Add("Accept", "application/json; odata=verbose");
            var endpointUrl = "/_api/contextinfo";
            var content = client.UploadString(endpointUrl, "POST");
            var data = JObject.Parse(content);
            return data["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
        }
    }
}

源代码:FileUploader.cs

用法

var userCredentials = GetCredentials(userName, password);
var sourcePath = @"C:\temp\jellyfish-25-mbps-hd-hevc.mkv"; //local file path
var targetFolderUrl = "/Shared Documents"; //library reltive url
FileUploader.ChunkedFileUpload(webUrl,
       userCredentials,
       sourcePath, 
       targetFolderUrl, 
       1024 * 1024 * 5, //5MB
       (offset, size) =>
       {
            Console.WriteLine("{0:P} completed", (offset / (float)size));
       });

参考

始终使用文件分块将 > 250 MB 的文件上传到 SharePoint Online

于 2019-07-10T08:32:44.167 回答