barracudanetworks / ArchiveStream-php

Archive streaming library for PHP
Other
77 stars 27 forks source link

zip file will not be dowloaded if zlib.output_compression is turned on (zlib.output_compression = On) in php.ini #22

Closed hchautrung closed 8 years ago

hchautrung commented 8 years ago

If zlib.output_compression is turn on by default the zip file can't be download. I have debugged and found that the header can't be sent in send_http_headers function.

To make it works need to turn zlib.output_compression Off Regards, Trung

johnmaguire commented 8 years ago

@hugohuynh Thanks for the report. zlib.output_compression I believe causes issues with output buffering. You said "I have debugged and found that the header can't be sent in send_http_headers function." Do you mean that the headers are not sending? Or did you try to add a header to the function to disable zlib.output_compression?

I believe you want to add an ini_set('zlib.output_compression', 'Off'); line prior to using ArchiveStream. It'd be great if you could report back on whether this works or not!

hchautrung commented 8 years ago

If zlib.output_compression = On in php.ini file, header("$key: $val") command in send_http_headers function will stop with the first value in the array. So that I mentioned "I have debugged and found that the header can't be sent in send_http_headers function." To resolve the problem I did as you suggest: punt ini_set('zlib.output_compression', 'Off') line prior to using ArchiveStream. IT WORKS, THANKS

However, I have setup another test server. Here is info

Ubuntu 10.04.4 PHP 5.3.2 Apache 2.2.14 GMP version 4.3.2 zlib.output_compression = Off

But ArchiveStream will not work, Please advice.

Thanks. Trung.

johnmaguire commented 8 years ago

Glad that worked. I will either add the ini_set() flag in ArchiveStream itself, or try to document this better. Unfortunately, there's a lot of flags and extensions that can cause issues with output buffering of different sorts (both set within php.ini, and within your web server).

Can you please create a page with the following contents:

<?php
phpinfo();

And then download the page, and send it as an attachment to jmaguire@barracuda.com? I'd like to see if you have any other known problematic settings on that may be interfering.

Additionally, can you describe what you mean by "ArchiveStream will not work"? When does it fail? How does it fail?

hchautrung commented 8 years ago

I have sent an email with subject ArchiveStream-php regarding phpinfo. I mentioned that "ArchiveStream will not work" mean the download process won't happen. I also debugged and found the same problem: header("$key: $val") command in send_http_headers function will stop with the first value in the array. Regards, Trung.

johnmaguire commented 8 years ago

@hugohuynh Are you getting any PHP errors, warnings, or notices in your logs?

Additionally, you haven't set any output prior to calling ArchiveStream have you? (Template header, page content, etc.) Headers can only be sent prior to any output being sent. An easy way to check is to add ob_start() at the very beginning of your application, then add ob_end_clean() before your ArchiveStream calls. This will break other code, but it's an easy way for us to determine if that's indeed the issue.

hchautrung commented 8 years ago

I haven't set any output prior to calling ArchiveStream. The same code work on my local server, But I will not work on test server (sent you email regarding phpinfo). I tried to turn on debug mode in my application and this is PHP warning. The warning mention @ the line 83 in Archive.php already sent. I hope can give you some tips to find out the problem. Thanks.

php-warning

@ Line 83 in Archive.php line 83

johnmaguire commented 8 years ago

Sweet, that's extremely helpful! So it looks like some output was sent to the browser (in Archive.php, on line 83). If you take a look at that line, we're calling ob_end_flush() repeatedly until there are no output buffers left. It seems somwhere in your application you called ob_start(), wrote some data, and then we (ArchiveStream) ended up flushing it to the browser in the __construct(). We might want to change that to ob_end_clean().

Can you try the following to verify that this is a valid fix?

Just before you create the ArchiveStream object, put a statement ob_end_clean().

If your issue isn't resolved, do the following:

while (ob_get_level() > 0) {
    ob_end_clean();
}

If the issue still isn't resolved, something else must be up.

If the issue is resolved, and you'd like to track down what is echoing data, remove the solution above and write the following instead: die(var_export(ob_get_clean(), true));. That should get you the data that was printed prior to ArchiveStream being initialized.

Please report back in either case, so we can update our code to call ob_end_clean() instead (and maybe log a warning?) if this fixes your issue.

hchautrung commented 8 years ago

Great !. I put ob_end_clean() before creating ArchiveStream object and it works like a charm!. But is it correct way to fix the problem?

johnmaguire commented 8 years ago

:+1:

Well, yes and no. :) For the library's purposes, we should probably be calling ob_end_clean() instead of ob_end_flush() to prevent issues like this. However, strictly speaking, it sounds like your application is outputting something you didn't expect.

In place of the ob_end_clean(); line, write the following instead: die(var_export(ob_get_clean(), true));. This will tell you what your application is trying to print, and perhaps help you to track down what is sending rogue output. :)

hchautrung commented 8 years ago

I can guarantee with you there is no ob_start function in my application (I did search text in my whole project many times). That's quite strange :-)

johnmaguire commented 8 years ago

@hugohuynh Are you using an application framework? It's very common for them to call ob_start() prior to doing much of anything. They generally will call ob_end_flush() when they are done with all processing.

In any case, I do highly recommend you track down where the output came from as you may experience other bugs in the future due to the same reason.

I've pushed a new version 1.0.2 with the change from ob_end_flush() to ob_end_clean() so we'll throw away any data in an output buffer rather than printing it (sort of a silly oversight on our part.) :)

Again, I recommend tracking down the source of rogue output anyway.

johnmaguire commented 8 years ago

Closing this issue. If you have any other problems feel free to open a new ticket. :)

hchautrung commented 8 years ago

Ok thank John. Appreciate your help !. Your library save me a lot of time. I use Yii framework. So I think there are some places they called ob_start(). Thanks a lot