为什么这个 Sharepoint Files.Add() 会导致 I/O 错误?

Why does this Sharepoint Files.Add() result in an I/O Error?

使用此代码:

    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

...我得到,“I/O 发生错误”(在 IOException 捕获块中)。就是这一行:

site.Files.Add(destination, ms);

...引发错误。是我的目的地还是内存流导致了问题? "destination" 是 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);

...我又回到了旧的 "I/O Error Occurred" 口头禅。

更新 3

由于 Sharepoint 站点的 "AllItems.aspx" 页面同时包含 "Documents" 和 "Lists",我想知道在这种情况下我是否不应该使用 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();

...但是这个猜测没有成功,因为它不会编译(我明白了,"The best overloaded method match for 'Microsoft.SharePoint.SPDocTemplateCollection.this[int]' has some invalid arguments" 和 "Argument 1: cannot convert from 'string' to 'int'")

这个有效:

. . .
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();
        }
    }
}

我改编自 Henry Zucchini 的回答 here