+1-888-365-2779
Try Now
More in this section

Forums / Bugs & Issues / Cannot use Document stream

Cannot use Document stream

14 posts, 0 answered
  1. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    06 Sep 2011
    Link to this post
    Hi,

    Consider the following method:

    public void CreateZip()
    {
        using (ZipFile zip = new ZipFile()) // ZipFile = Ionic.Zip.ZipFile
        {
            foreach (var doc in this.documents) // documents is a List of Telerik.Sitefinity.Libraries.Model.Document objects
            {
                var stream = LibrariesManager.GetManager().Download(doc);
                zip.AddEntry(doc.Title + doc.Extension, stream);
            }
     
            zip.Save(@"C:\test.zip");
        }
    }

    This does not work. It seems there is a problem with the stream, and I cannot do anything with them.
    stream.CopyTo or zip.Save take ages then end on a OutOfMemoryException.
    I tried to write the stream into a byte array, too, but I got a NotSupportedException.

    If I change the "var stream" line with this line, then it works:

    var stream = new System.IO.FileStream(@"C:\test.txt", System.IO.FileMode.Open);

    Which makes me think there is a problem with the stream I get from LibrariesManager.GetManager().Download(doc).
    Am I doing it wrong or something? Why does the Download method return a useless stream?

    Sounds like a bug to me, so I'm reporting this here. This is with Sitefinity 4.2.

    Thanks.
  2. Veronica
    Veronica avatar
    125 posts
    Registered:
    30 Jan 2015
    07 Sep 2011
    Link to this post
    Hello Thomas,

    Thank you for the detailed description of the issue.

    Actually I am wondering whether I miss something in reproducing the issue as I tested your code and I successfully saved a .zip file on my local drive. Also to check whether the stream is OK I tried to save it by using a FileStream:

    public void CreateZip()
           {
               LibrariesManager manager = LibrariesManager.GetManager();
               using (ZipFile zip = new ZipFile()) // ZipFile = Ionic.Zip.ZipFile
               {
                   IQueryable<Document> docList = manager.GetDocuments().Where(d => d.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live);
                   foreach (var doc in docList) // documents is a List of Telerik.Sitefinity.Libraries.Model.Document objects
                   {
                       var stream = manager.Download(doc);
     
                       FileStream fileStream = new FileStream(@"C:/MyFiles", FileMode.Create);
                       using (fileStream)
                       {
                           // Fill the bytes[] array with the stream data
                           byte[] bytesInStream = new byte[stream.Length];
                           stream.Read(bytesInStream, 0, bytesInStream.Length);
     
                           // Use FileStream object to write to the specified file
                           fileStream.Write(bytesInStream, 0, bytesInStream.Length);
     
                       }
     
                       //zip.AddFileStream(doc.Title + doc.Extension, "", stream);
     
                   }
                    
                   //zip.Save(@"C:\test.zip");
               }
           }


    However there is no method zip.AddEntry() in version 4.2. Instead I used zip.AddFileStream as you can see in the code above.

    Please let me know if I miss something.

    All the best,
    Veronica Milcheva
    the Telerik team

    Thank you for being the most amazing .NET community! Your unfailing support is what helps us charge forward! We'd appreciate your vote for Telerik in this year's DevProConnections Awards. We are competing in mind-blowing 20 categories and every vote counts! VOTE for Telerik NOW >>

  3. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    07 Sep 2011
    Link to this post
    Hi Veronica,

    I made a mistake: I should have used stream.Read rather than stream.Write to create the byte array.
    With the byte array, I got it to work.

    So this didn't work (not sure why):

    var stream = LibrariesManager.GetManager().Download(doc);
    zip.AddEntry(doc.Title + doc.Extension, stream);

    But this worked:

    byte[] bytes = this.GetBytes(doc);
    zip.AddEntry(doc.Title + doc.Extension, bytes);
      
    (...)
      
    private byte[] GetBytes(Document document)
    {
        var manager = LibrariesManager.GetManager();
        using (var stream = manager.Download(document))
        {
            byte[] bytes = new byte[stream.Length];
            stream.Read(bytes, 0, bytes.Length);
            return bytes;
        }
    }


    Thanks for your help.

    Edit 1: for the record, for the file name, I ended up not using the doc.Title but doc.UrlName instead, which is cleaner and avoids issues when 2 files have the same title.

    Edit 2: "However there is no method zip.AddEntry() in version 4.2. Instead I used zip.AddFileStream as you can see in the code above."
    As specified in the code comment, the zip object I use is actually a Ionic.Zip.ZipFile, which has an AddEntry method.
  4. Veronica
    Veronica avatar
    125 posts
    Registered:
    30 Jan 2015
    13 Sep 2011
    Link to this post
    Hello Thomas,

    Please accept my apologies for the late reply.

    I am glad that you found a workaround of the issue. However I wonder why the first one is not working on your side. If the workaround satisfies your requirement I'll close the thread, otherwise I'll continue researching the issue although both scenarios work on my side.

    Regards,
    Veronica Milcheva
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  5. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    13 Sep 2011
    Link to this post
    Hi Veronica,

    I'm thinking you may not have been able to reproduce my problem because you used a Telerik.Sitefinity.Utilities.Zip.ZipFile rather than Ionic.Zip.ZipFile. It may be interesting to see what makes this fail with Ionic.Zip, as it's possible there is something wrong with the stream that may only cause a failure in certain circumstances (ie: it could also happen in other cases, not just with Ionic.Zip).

    So as far as I'm concerned, I've worked around this issue and can now move on to other things, so this doesn't block me anymore. But for the future of Sitefinity, you might want to investigate this some more to fix potential issues. Of course, it's also possible that it's Ionic.Zip that does something wrong (I've never had any problems with this library, though).
  6. Veronica
    Veronica avatar
    125 posts
    Registered:
    30 Jan 2015
    17 Sep 2011
    Link to this post
    Hi Thomas,

    I've tested with Ionic library and I can confirm that the following code works:
    public void CreateZip()
            {
                LibrariesManager manager = LibrariesManager.GetManager();
                using (ZipFile zip = new ZipFile()) // ZipFile = Ionic.Zip.ZipFile
                {
                    IQueryable<Document> docList = manager.GetDocuments().Where(d => d.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live);
                    foreach (var doc in docList) // documents is a List of Telerik.Sitefinity.Libraries.Model.Document objects
                    {
     
                        var stream = LibrariesManager.GetManager().Download(doc);
     
                        zip.AddEntry(doc.Title + doc.Extension, stream);
     
                    }
                    zip.Save(@"C:\test.zip");
                }
            }

    The only difference between mine and your code is that I am retrieving the Live documents:
    IQueryable<Document> docList = manager.GetDocuments().Where(d => d.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live);

    In your code I cannot see how are you retrieving the documents in this.documents.

    Kind regards,
    Veronica Milcheva
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  7. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    19 Sep 2011
    Link to this post
    Hi Veronica,

    This how I retrieve the documents:

    private void LoadDocuments()
    {
        this.docIds = this.GetDocumentIds(); // docIds is of type IEnumerable<Guid>
     
        this.documents = new List<Document>();
        foreach (Guid id in this.docIds)
        {
            var doc = App.WorkWith().Documents().Publihed().FirstThat(d => d.Id == id).Get();
            this.documents.Add(doc);
        }
    }
  8. Lubomir Velkov
    Lubomir Velkov avatar
    688 posts
    Registered:
    03 Nov 2014
    22 Sep 2011
    Link to this post
    Hello Thomas,

    In this case could you provide us with the source of this function:

    this.GetDocumentIds()

    Since an Id may be an Id for a draft, live or temp version of a Document, so it is important what Ids do you actually retrieve with this function.

    Greetings,
    Lubomir Velkov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  9. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    22 Sep 2011
    Link to this post
    Hi Lubomir,

    The GetDocumentIds method loads ids from session, so I'll just skip to the relevant part (ie: how documents are loaded in the first place):

    private IEnumerable<Document> GetAllLibraryDocuments()
    {
        var docs = new List<Document>();
     
        var allDocs = App.WorkWith().Documents().Publihed().Get();
        foreach (var doc in allDocs)
        {
            if (doc.Library.UrlName == this.LibraryUrlName)
            {
                docs.Add(doc);
            }
        }
     
        return docs;
    }

    The ids originally come from these documents.

    PS: the reason I do a foreach loop to retrieve the document is because I couldn't get the Where clause to work here.
  10. Lubomir Velkov
    Lubomir Velkov avatar
    688 posts
    Registered:
    03 Nov 2014
    22 Sep 2011
    Link to this post
    Hello Thomas,

    Ok so using your code to retrieve the documents you can't get the ZipFile to actually create a Zip file from them?

    Regards,
    Lubomir Velkov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  11. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    22 Sep 2011
    Link to this post
    I managed to do it by converting the streams to byte arrays, but I couldn't do it directly from the streams, no.
  12. Lubomir Velkov
    Lubomir Velkov avatar
    688 posts
    Registered:
    03 Nov 2014
    26 Sep 2011
    Link to this post
    Hi Thomas,

    Ok, so is the workaround with converting the Stream to byte array working for you or do you need any additional help for this issue?

    Regards,
    Lubomir Velkov
    the Telerik team
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  13. Thomas
    Thomas avatar
    223 posts
    Registered:
    19 Jan 2011
    26 Sep 2011
    Link to this post
    Hi Lubomir,

    The workaround works, so I'm fine. Thank you.
  14. Anup
    Anup avatar
    3 posts
    Registered:
    24 Jun 2014
    06 Feb 2015
    Link to this post
    • public byte[] GetBytes(Guid Id)
              {
                  var manager = LibrariesManager.GetManager();
                  Document doc = manager.GetDocuments().Where(x => x.Id == Id).FirstOrDefault();
                  using (Stream stream = manager.Download(doc.Id))
                  {
                      byte[] bytes = new byte[stream.Length];
                      stream.Read(bytes, 0, bytes.Length);
                      return bytes;
                  }
              }
14 posts, 0 answered