Cannot use Document stream

Posted by Community Admin on 04-Aug-2018 10:13

Cannot use Document stream

All Replies

Posted by Community Admin on 06-Sep-2011 00:00

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.

Posted by Community Admin on 07-Sep-2011 00:00

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 >>

Posted by Community Admin on 07-Sep-2011 00:00

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.

Posted by Community Admin on 13-Sep-2011 00:00

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

Posted by Community Admin on 13-Sep-2011 00:00

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).

Posted by Community Admin on 17-Sep-2011 00:00

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

Posted by Community Admin on 19-Sep-2011 00:00

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);
    

Posted by Community Admin on 22-Sep-2011 00:00

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

Posted by Community Admin on 22-Sep-2011 00:00

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.

Posted by Community Admin on 22-Sep-2011 00:00

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

Posted by Community Admin on 22-Sep-2011 00:00

I managed to do it by converting the streams to byte arrays, but I couldn't do it directly from the streams, no.

Posted by Community Admin on 26-Sep-2011 00:00

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

Posted by Community Admin on 26-Sep-2011 00:00

Hi Lubomir,

The workaround works, so I'm fine. Thank you.

Posted by Community Admin on 06-Feb-2015 00:00

  • 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;
               
           

This thread is closed