-
Notifications
You must be signed in to change notification settings - Fork 5k
Add Flush to ZipArchive #24149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It appears that this is due to not flushing the underlying zip. In .NET Framework it is flushed, but not in .NET Core. I'll try adding that in and see if it works. |
@ianhays ZipArchive does not have a Flush method. Is there a way to flush the current archive state to a stream, or is this part of the issue to get streaming support for compression? |
I'm not sure why ZipArchive in netcore doesn't have a flush method. It was ported to CoreFX without one. It could be that it was removed since it was internal-only in netfx and not used in netcore. We could probably add it as public, at least for ZipArchiveMode.Create. I'm not sure how that would affect being able to open some entries though. We would need to add lots of tests to first verify the netfx Flushing behavior - which may be tricky since it's not exposed through ZipArchive - then try to match that in core. At that point a streaming API may be the better solution. |
Yeah - I took a shot at just calling the WriteFile method (which is what the Dispose method calls) in lieu of a flush and it caused a lot of problems. It seems to close streams, so it expects to be called in the dispose. Exposing it would be nice, but I agree that there will be a need to add a bunch of tests for it. We seem to be finding many issues with System.IO.Packaging in the DocumentFormat.OpenXml library that would be fixed with the streaming API... |
Any progress on this? we use DocumentFormat.OpenXml and it has intentional bugs that keep parity between .net fx and .net core. see dotnet/Open-XML-SDK#380 |
There hasn't been any progress that I'm aware of, no. I've updated the title and the tags with the current state of the issue and marked it as The work item here is to plan an API addition of Flush to ZipArchive. To do that, a formal proposal will have to be made and the design questions in the comments above should be answered. |
So I have just hit this issue too. Porting some code from FX to .Net. Need ZipPackage to be able to flush the stream. Is there any workaround ? Else, I can take on adding the API to ZipArchive. |
Sorry, replaced my github account. So the message above is from me. I have made the changes to add a Flush API and added tests to verify. I will follow through the procedures for getting the API and change approved. |
when will the flush function will be added? |
@SinxHe , unfortunately fixing this issue is a bit more tricky than I initially anticipated. As I have managed to work around this issue for now, I am not sure when I will be able to get back to work on a fix for this. |
@odhanson Thanks for taking a look at this. Can you share a fork with your current progress so someone else can build off of what you've tried? |
Sure. I have made a fork under my account: There are two commits, the first adds the API and some tests. The second implements the API, and adds some tests that failed my implementation :(. So the good news is, that we do have a bunch of tests to base off of. |
Hi, I'm wondering if there has been any progress on this issue? I'm seeing an out of memory exception when trying to create a huge spreadsheet. As the OpenXmlWriter is writing contents the memory usage continues to creep up, but there is currently no way to flush the data so the entire contents of the sheet remain in memory. I'm also curious to know what the work around is. |
Thank you all for the patience. We are planning work for .NET 7 and fixing the bugs affecting System.IO.Packaging is most likely going to be among our top priorities for the Compression area specifically. @odhanson Thank you for the code you provided: https://github.com/odhanson/corefx/tree/dev/Flush . It was extremely helpful! I debugged it to understand the problem better (I adapted them to dotnet/runtime of course) and I would like to share the following feedback:
The logic to handle creation and update is too convoluted and intermixed. So before making any After we refactor the code, we could implement I also need to keep in mind Ian's concern shared above:
@twsouthwick I'll continue investigating how feasible it is to add |
@twsouthwick (and/or anyone else monitoring this issue), I have some questions that arised after I read this: Let's ignore for a moment what .NET Framework is doing. What behavior do you expect from
Non-seekable streamLet's say you're working with a stream that is being sent to you from the network. Deleting
Note: We currently cannot open a Adding
Seekable streamLet's say you're working with a zip file loaded from disk using a Deleting
AddingI think the behavior would be the same as described for non-seekable. Updating a file entry's stream
|
If I understood correctly, the fix is planned for .NET 8 time?😥 |
Any progress on this? |
Hello, could you please recommend third party package with zip flush support? |
I recently submitted #102704, which implements the logic @carlossanlop describes in Flush for seekable streams (although I've admittedly only just seen the comment - wish I'd seen it earlier!) Hopefully this disposes of the more complex case. The only ZipArchiveMode which can modify a non-seekable stream is Create. The first Flush here is simple, and I'm tempted say we should throw an exception for any subsequent Flush calls:
|
Looks like folks are still running into this. Given that IO.Packaging is used for many document formats I can see that Flush is a valuable feature (save without close). @edwardneal @carlossanlop - how close do you think we are to being able to support Flush on ZipArchive? |
I think we're fairly close - We have various blocks (central directory, central directory locator, etc.) at the end of the file, and Regardless, we'll need to plumb this through to An initial API proposal is: namespace System.IO.Compression;
public class ZipArchive
{
+ // If flushFinalBlock is set to false, the blocks at the end of the file won't be written
+ // This could instead be a FlushMode enum, with a default value of Finalize.
+ // Alternatively, we could remove the parameter and make every Flush write the trailing blocks.
+ public void Flush(bool flushFinalBlock = true);
+ public ValueTask FlushAsync(bool flushFinalBlock = true, CancellationToken cancellationToken = default);
+ protected virtual void FlushCore(bool flushFinalBlock);
+ protected virtual ValueTask FlushAsyncCore(bool flushFinalBlock, CancellationToken cancellationToken);
}
// Optional. Changes below only apply to the .NET Core target.
namespace System.IO.Packaging;
public abstract class Package
{
public void Flush()
- { /* Package-specific logic */ }
+ => Flush(flushFinalBlock: true);
+ public void Flush(bool flushFinalBlock)
+ {
+ /* Package-specific logic */
+ if (flushFinalBlock) { FlushCore(); }
+ else { FlushIncrementalCore(); }
+ }
+ protected virtual void FlushIncrementalCore() => FlushCore();
}
public sealed class ZipPackage : Package
{
+ protected override void FlushIncrementalCore();
} API and behavioural notes:
|
When creating a package on .NET Core, you have to call Dispose or Close to get the contents written out to the underlying stream. This works on .NET Framework, but fails on .NET Core:
The text was updated successfully, but these errors were encountered: