Почему этот Sharepoint Files.Add () приводит к ошибке ввода-вывода?

С помощью этого кода:

    using (var ms = new MemoryStream())
    {
        using (var doc = new Document(PageSize.A4, 25, 25, 10, 10)) 
        {
            //Create a writer that's bound to our PDF abstraction and our 
stream
            using (var writer = PdfWriter.GetInstance(doc, ms))
            {

                //Open the document for writing
                doc.Open();

                . . .

            }
        // File has been generated, now save it
        try
        {
            var bytes = ms.ToArray();
            String pdfFileID = GetYYYYMMDDAndUserNameAndAmount();
            String pdfFileName = String.Format("DirectPayDynamic_{0}.pdf", 
pdfFileID);
            String fileFullpath = 
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirector
y), pdfFileName); 
            String fileLinkBase = "Generated PDF: <a href=\"{0}\">{1}</a>";
            String filelink = String.Format(fileLinkBase, fileFullpath, 
pdfFileName);

            File.WriteAllBytes(fileFullpath, bytes);
            AddVerticalSpace();                    

            var pdflink = new Label
            {
                CssClass = "finaff-webform-field-label",
                Text = filelink
            };
            this.Controls.Add(pdflink); 

    // NOTE: This is the new (non-working, exception-throwing) part of the 
code, where we're trying to save the PDF file to a Sharepoint Document Library
            string destination = String.Format("DirectPayPDFForms/{0}", 
pdfFileName); 
            SPSite siteCollection = new SPSite(siteUrl);
            SPWeb site = SPContext.Current.Web; 
            site.Files.Add(destination, ms); // this is the line that fails
    // end of new code      
        }
        catch (DocumentException dex)
        {
            exMsg = dex.Message;
        }
        catch (IOException ioex)
        {
            exMsg = ioex.Message;
        }
        catch (Exception ex)
        {
            exMsg = ex.Message;
            ; // for debugging: What is "ex" here?
        }
    } // using (var ms = new MemoryStream())            
} // GeneratePDF

... Я получаю сообщение «Произошла ошибка ввода-вывода» (в блоке catch IOException). Это такая строка:

site.Files.Add(destination, ms);

... это вызывает ошибку. Причина проблемы в моем пункте назначения или в потоке памяти? «пункт назначения» - это имя библиотеки документов Sharepoint (DirectPayPDFForms) плюс сгенерированное имя для файла. Без этого нового кода метод работает нормально и помещает PDF-файл на сервер (но это не то место, где мы хотим - нам нужно, чтобы он сначала перешел в библиотеку документов).

ОБНОВИТЬ

Я получаю то же исключение, заменяя проблемный блок кода выше на это:

private void SavePDFToDocumentLibrary(MemoryStream memstrm)
{
    string doclib = "DirectPayPDFForms";
    try
    {
        using (SPSite site = new SPSite(siteUrl))
        {
            using (SPWeb web = site.RootWeb)
            {
                SPList list = web.Lists[doclib];
                SPListItem spli = list.Items.Add();
                spli["Title"] = String.Format("DirectPayPDFForms-{0}-{1}", GetUserId(), GetListTitleTimeStamp());

                if (null != memstrm)
                {
                    web.Files.Add(doclib, memstrm); 
                }
                // If this works, update at least some of the fields, such as Created, CreatedBy, etc.
                spli.Update();
            }
        }
    }
    catch (Exception ex)
    {
        String s = String.Format("Exception is {0}", ex.Message);
    }
}

Этот тип кода работает в другом экземпляре (таким образом я могу успешно сохранять значения в списке), поэтому проблема должна быть в чем-то специфическом для библиотеки документов. Нужно ли мне сохранять документ в определенном поле в библиотеке документов?

ОБНОВЛЕНИЕ 2

Я тоже пробовал это:

string saveloc = String.Format(@"{0}\{1}", doclib, filename);

... с тем же результатом.

И это:

string saveloc = String.Format(@"{0}\{1}\{2}", siteUrl, doclib, filename);

... который, по крайней мере, обеспечил некоторое разнообразие, за исключением: «Недействительный URI: имя хоста не может быть проанализировано.»

С этим:

string saveloc = String.Format("{0}/{1}/{2}", siteUrl, doclib, filename);

... Я вернулся к старой мантре «Произошла ошибка ввода-вывода».

ОБНОВЛЕНИЕ 3

Поскольку на странице AllItems.aspx для сайта Sharepoint есть и «Документы», и «Списки», мне интересно, не следует ли мне использовать в этом случае не List, а Document. IOW, возможно, мой код должен быть примерно таким:

SPDocTemplateCollection spdoctemplatecoll = web.DocTemplates;
SPDocumentLibrary spdoclib = spdoctemplatecoll[doclib];
SPListItem spli = spdoclib.Items.Add();

... где он сейчас:

SPList list = web.Lists[doclib];
SPListItem spli = list.Items.Add();
SPListItem spli = list.Items.Add();

... но это предположение не срабатывает, так как оно не компилируется (я получаю: «Лучшее совпадение перегруженного метода для 'Microsoft.SharePoint.SPDocTemplateCollection.this [int]' имеет некоторые недопустимые аргументы» и «Аргумент 1: невозможно преобразовать от 'строка' до 'int' ")


person B. Clay Shannon    schedule 28.07.2015    source источник


Ответы (1)


Это работает:

. . .
SavePDFToDocumentLibrary(fileFullpath); // instead of trying to send the memory stream, using the file saved on the server
. . .

private void SavePDFToDocumentLibrary(String fullpath)
{
    String fileToUpload = fullpath;
    String sharePointSite = siteUrl;
    String documentLibraryName = "DirectPayPDFForms";

    using (SPSite oSite = new SPSite(sharePointSite))
    {
        using (SPWeb oWeb = oSite.OpenWeb())
        {
            if (!System.IO.File.Exists(fileToUpload))
            {
                throw new FileNotFoundException("File not found.", fileToUpload);
            }

            SPFolder doclib = oWeb.Folders[documentLibraryName];

            // Prepare to upload
            Boolean replaceExistingFiles = true;
            String fileName = System.IO.Path.GetFileName(fileToUpload);
            FileStream fileStream = File.OpenRead(fileToUpload);

            // Upload document
            SPFile spfile = doclib.Files.Add(fileName, fileStream, replaceExistingFiles);

            // Commit 
            doclib.Update();
        }
    }
}

Я адаптировал его из ответа Генри Цуккини здесь.

person B. Clay Shannon    schedule 28.07.2015
comment
Я предполагаю, что это связано с тем, что API-интерфейс базового отдыха требует, чтобы был установлен заголовок Content-Length. MemoryStream не знает своей длины, поэтому не может установить Content-Length. FileStream знает свою длину, поэтому может правильно установить заголовок - person Alex; 09.07.2020