Загрузка файловых блоков в SPS 2013 - метод «StartUpload» не существует в строке - PullRequest
6 голосов
/ 24 июня 2019

Я пытаюсь загрузить большой файл (1 ГБ) из кода в SharePoint 2013 на прем .Я следовал этому учебнику , я скачал из NuGet пакет "Microsoft.SharePointOnline.CSOM" и попробовал этот фрагмент кода:

public Microsoft.SharePoint.Client.File UploadFileSlicePerSlice(ClientContext ctx, string libraryName, string fileName, int fileChunkSizeInMB = 3)
    {
        // Each sliced upload requires a unique ID.
        Guid uploadId = Guid.NewGuid();

        // Get the name of the file.
        string uniqueFileName = Path.GetFileName(fileName);

        // Ensure that target library exists, and create it if it is missing.
        if (!LibraryExists(ctx, ctx.Web, libraryName))
        {
            CreateLibrary(ctx, ctx.Web, libraryName);
        }
        // Get the folder to upload into. 
        List docs = ctx.Web.Lists.GetByTitle(libraryName);
        ctx.Load(docs, l => l.RootFolder);
        // Get the information about the folder that will hold the file.
        ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
        ctx.ExecuteQuery();

        // File object.
        Microsoft.SharePoint.Client.File uploadFile;

        // Calculate block size in bytes.
        int blockSize = fileChunkSizeInMB * 1024 * 1024;

        // Get the information about the folder that will hold the file.
        ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
        ctx.ExecuteQuery();


        // Get the size of the file.
        long fileSize = new FileInfo(fileName).Length;

        if (fileSize <= blockSize)
        {
            // Use regular approach.
            using (FileStream fs = new FileStream(fileName, FileMode.Open))
            {
                FileCreationInformation fileInfo = new FileCreationInformation();
                fileInfo.ContentStream = fs;
                fileInfo.Url = uniqueFileName;
                fileInfo.Overwrite = true;
                uploadFile = docs.RootFolder.Files.Add(fileInfo);
                ctx.Load(uploadFile);
                ctx.ExecuteQuery();
                // Return the file object for the uploaded file.
                return uploadFile;
            }
        }
        else
        {
            // Use large file upload approach.
            ClientResult<long> bytesUploaded = null;

            FileStream fs = null;
            try
            {
                fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                using (BinaryReader br = new BinaryReader(fs))
                {
                    byte[] buffer = new byte[blockSize];
                    Byte[] lastBuffer = null;
                    long fileoffset = 0;
                    long totalBytesRead = 0;
                    int bytesRead;
                    bool first = true;
                    bool last = false;

                    // Read data from file system in blocks. 
                    while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        totalBytesRead = totalBytesRead + bytesRead;

                        // You've reached the end of the file.
                        if (totalBytesRead == fileSize)
                        {
                            last = true;
                            // Copy to a new buffer that has the correct size.
                            lastBuffer = new byte[bytesRead];
                            Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
                        }

                        if (first)
                        {
                            using (MemoryStream contentStream = new MemoryStream())
                            {
                                // Add an empty file.
                                FileCreationInformation fileInfo = new FileCreationInformation();
                                fileInfo.ContentStream = contentStream;
                                fileInfo.Url = uniqueFileName;
                                fileInfo.Overwrite = true;
                                uploadFile = docs.RootFolder.Files.Add(fileInfo);

                                // Start upload by uploading the first slice. 
                                using (MemoryStream s = new MemoryStream(buffer))
                                {
                                    // Call the start upload method on the first slice.
                                    bytesUploaded = uploadFile.StartUpload(uploadId, s);
                                    ctx.ExecuteQuery();//<------here exception
                                    // fileoffset is the pointer where the next slice will be added.
                                    fileoffset = bytesUploaded.Value;
                                }

                                // You can only start the upload once.
                                first = false;
                            }
                        }
                        else
                        {
                            // Get a reference to your file.
                            uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);

                            if (last)
                            {
                                // Is this the last slice of data?
                                using (MemoryStream s = new MemoryStream(lastBuffer))
                                {
                                    // End sliced upload by calling FinishUpload.
                                    uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
                                    ctx.ExecuteQuery();

                                    // Return the file object for the uploaded file.
                                    return uploadFile;
                                }
                            }
                            else
                            {
                                using (MemoryStream s = new MemoryStream(buffer))
                                {
                                    // Continue sliced upload.
                                    bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
                                    ctx.ExecuteQuery();
                                    // Update fileoffset for the next slice.
                                    fileoffset = bytesUploaded.Value;
                                }
                            }
                        }

                    } // while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
                }
            }
            finally
            {
                if (fs != null)
                {
                    fs.Dispose();
                }
            }
        }

        return null;
    }

Но я получаю исключение времени выполнения: ServerExecution с сообщением: метод "StartUpload" не существует в строке "ctx.ExecuteQuery ();" (<- я пометил эту строку в коде) </p>

Я также пытался с Пакет SharePoint2013 и метод "startupload" не поддерживаются в этом пакете.

ОБНОВЛЕНИЕ:

Код Адама работал для файлов ~ 1 ГБ, оказываетсячто внутри web.config в пути: C:\inetpub\wwwroot\wss\VirtualDirectories\{myport}\web.config

в части <requestLimit maxAllowedContentLength="2000000000"/> в байтах , а не килобайт , как я думал в начале, поэтомуЯ изменил на 2000000000, и он работал.

Ответы [ 3 ]

2 голосов
/ 11 июля 2019

метод для загрузки файла 1 ГБ на SP 2013 с использованием CSOM, который работает (тестировался и разрабатывался в течение пары дней, пробуя разные подходы :))



    try
    {
        Console.WriteLine("start " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());

        using (ClientContext context = new ClientContext("[URL]"))
        {
            context.Credentials = new NetworkCredential("[LOGIN]","[PASSWORD]","[DOMAIN]");
            context.RequestTimeout = -1;
            Web web = context.Web;
            if (context.HasPendingRequest)
                context.ExecuteQuery();

            byte[] fileBytes;
            using (var fs = new FileStream(@"D:\OneGB.rar", FileMode.Open, FileAccess.Read))
            {
                fileBytes = new byte[fs.Length];
                int bytesRead = fs.Read(fileBytes, 0, fileBytes.Length);
            }

            using (var fileStream = new System.IO.MemoryStream(fileBytes))
            {
                Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, "/Shared Documents/" + "OneGB.rar", fileStream, true);
            }
        }

        Console.WriteLine("end " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
    }
    catch (Exception ex)
    {
        Console.WriteLine("error -> " + ex.Message);
    }
    finally
    {
        Console.ReadLine();
    }

Кроме того, мне пришлось:

  • увеличить максимальную загрузку файла в ЦС для этого веб-приложения,
  • установить в ЦС для этого веб-приложения «Проверка безопасности веб-страницы» на Никогда (в этой ссылке естьэкран, как его настроить)
  • продлить тайм-аут на IIS

и окончательный результат:

извините за язык, но я обычно работаю в PL

enter image description here

вся история определена здесь post

0 голосов
/ 09 июля 2019

Я ищу способ загрузки 1 ГБ файла в SharePoint 2013

. Вы можете изменить предел загрузки с помощью PowerShell ниже:

$a = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$a.ClientRequestServiceSettings.MaxReceivedMessageSize = 209715200
$a.Update()

Ссылки:

https://thuansoldier.net/4328/

https://blogs.msdn.microsoft.com/sridhara/2010/03/12/uploading-files-using-client-object-model-in-sharepoint-2010/

https://social.msdn.microsoft.com/Forums/en-US/09a41ba4-feda-4cf3-aa29-704cd92b9320/csom-microsoftsharepointclientserverexception-method-8220startupload8221-does-not-exist?forum=sharepointdevelopment

Обновление:

SharePoint CSOMразмер запроса очень ограничен, он не может превышать 2 МБ, и вы не можете изменить этот параметр в среде Office 365.Если вам нужно загружать большие файлы, вы должны использовать REST API.Вот ссылка MSDN https://msdn.microsoft.com/en-us/library/office/dn292553.aspx

См. Также:

https://gist.github.com/vgrem/10713514

Загрузка файла в SharePoint 2013 с использованием REST API

Ref: https://sharepoint.stackexchange.com/posts/149105/edit (см. 2-й ответ).

0 голосов
/ 25 июня 2019

Установите библиотеку CSOM SharePoint Online, используя приведенную ниже команду.

Install-Package Microsoft.SharePointOnline.CSOM -Version 16.1.8924.1200

Затем используйте приведенный ниже код для загрузки большого файла.

int blockSize = 8000000; // 8 MB
string fileName = "C:\\temp\\6GBTest.odt", uniqueFileName = String.Empty;
long fileSize;
Microsoft.SharePoint.Client.File uploadFile = null;
Guid uploadId = Guid.NewGuid();

using (ClientContext ctx = new ClientContext("siteUrl"))
{
    ctx.Credentials = new SharePointOnlineCredentials("user@tenant.onmicrosoft.com", GetSecurePassword());
    List docs = ctx.Web.Lists.GetByTitle("Documents");
    ctx.Load(docs.RootFolder, p => p.ServerRelativeUrl);

    // Use large file upload approach
    ClientResult<long> bytesUploaded = null;

    FileStream fs = null;
    try
    {
        fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        fileSize = fs.Length;
        uniqueFileName = System.IO.Path.GetFileName(fs.Name);

        using (BinaryReader br = new BinaryReader(fs))
        {
            byte[] buffer = new byte[blockSize];
            byte[] lastBuffer = null;
            long fileoffset = 0;
            long totalBytesRead = 0;
            int bytesRead;
            bool first = true;
            bool last = false;

            // Read data from filesystem in blocks
            while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
            {
                totalBytesRead = totalBytesRead + bytesRead;

                // We've reached the end of the file
                if (totalBytesRead <= fileSize)
                {
                    last = true;
                    // Copy to a new buffer that has the correct size
                    lastBuffer = new byte[bytesRead];
                    Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
                }

                if (first)
                {
                    using (MemoryStream contentStream = new MemoryStream())
                    {
                        // Add an empty file.
                        FileCreationInformation fileInfo = new FileCreationInformation();
                        fileInfo.ContentStream = contentStream;
                        fileInfo.Url = uniqueFileName;
                        fileInfo.Overwrite = true;
                        uploadFile = docs.RootFolder.Files.Add(fileInfo);

                        // Start upload by uploading the first slice.
                        using (MemoryStream s = new MemoryStream(buffer))
                        {
                            // Call the start upload method on the first slice
                            bytesUploaded = uploadFile.StartUpload(uploadId, s);
                            ctx.ExecuteQuery();
                            // fileoffset is the pointer where the next slice will be added
                            fileoffset = bytesUploaded.Value;
                        }

                        // we can only start the upload once
                        first = false;
                    }
                }
                else
                {
                    // Get a reference to our file
                    uploadFile = ctx.Web.GetFileByServerRelativeUrl(docs.RootFolder.ServerRelativeUrl + System.IO.Path.AltDirectorySeparatorChar + uniqueFileName);

                    if (last)
                    {
                        // Is this the last slice of data?
                        using (MemoryStream s = new MemoryStream(lastBuffer))
                        {
                            // End sliced upload by calling FinishUpload
                            uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
                            ctx.ExecuteQuery();

                            // return the file object for the uploaded file
                            return uploadFile;
                        }
                    }
                    else
                    {
                        using (MemoryStream s = new MemoryStream(buffer))
                        {
                            // Continue sliced upload
                            bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
                            ctx.ExecuteQuery();
                            // update fileoffset for the next slice
                            fileoffset = bytesUploaded.Value;
                        }
                    }
                }

            }
        }
    }
    finally
    {
        if (fs != null)
        {
            fs.Dispose();
        }
    }
}

Или загрузите пример кода с GitHub.

Загрузка большого файла с CSOM

...