http://www.perlmonks.org?node_id=641333

perlCrazy has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I am having problem in displaying large size of varaible on web page. Below is the Example:
$retHashRef{$viewItem[0]} = $viewStr;
Here in this example I am returning \%retHashRef to calling program. $viewStr is very big in size lets say 2 MB.
When I do print $viewStr, it does print. But when i am trying to print inside HTML like this it doesn't display anything:
foreach my $row (keys %$dbDDL) { push @rowArr, '<pre> ' . '<font size=2>' .$dbDDL->{$row} . '</font>' +. '</pre>' ; &P3::util::HTML::doTableDetailRow($altColor, @rowArr); }
Can somebody Please advice me why this is happening ? Thanks in advance.
Note : When I do just print $dbDDL->{$row}, it does print.
Update: Thanks for the response. And sorry for not being very clear in my post.
When I try to display small string it does display properly. This happens only when string size is very big.
Regarding P3::Util::HTML module, that is our own module and there is no problem in this.
Here is the code :
module name : Dbschema.pm this is portion of method that populate the hash for string. sub getViewProcs { my $lineNo=0; my $text; while (my $row = $sth->fetchrow_arrayref()) { ## Store + all columns value in array of hash #Add ownership information to views $text = $row->[0]; if ( !$lineNo ) { $text =~ s/^\s*create\s+view\s+$viewItem[0]\s+ +/create view $viewItem[1].$viewItem[0] /i; } $lineNo++; for (my $i=0;$i<length($text);$i+=100) { my $slice = substr($text, $i, 100); $viewStr .= $slice; } } } $retHashRef{$viewItem[0]} = $viewStr; } my ($procDDL) = $self->getViewProcs($dbase,'P'); if($procDDL){ foreach my $procStr (keys %$procDDL) { $pDDL .= "$procDDL->{$procStr}"; } $pDDL .= "$goTxt"; } $retHashRef{PROC} = $pDDL;
this is the code that does display on browswer.
This is the script that does take care of displaying og HTML my ($dbDDL) = $dbObj->getDbSchema($sourcedb,'%'); &P3::util::HTML::startTable("$sourcedb ",undef,undef,undef,un +def,$colexp); foreach my $row (keys %$dbDDL) { &P3::util::HTML::doTableColAttributes(''); # Reset the Co +lumn Attributes $altColor = !$altColor; my @rowArr; push @rowArr, '<pre> ' . '<font size=2>' .$dbDDL->{$row} +. '</font>' . '</pre>' ; &P3::util::HTML::doTableDetailRow($altColor, @rowArr); }

Replies are listed 'Best First'.
Re: having problem in displaying large size of variable on web page
by graff (Chancellor) on Sep 27, 2007 at 13:09 UTC
    I'm not sure I understand that snippet correctly, but it looks like, if there were, say, 3 elements in your hash, then the output might be something like:
    <table> <tr> ... first element </tr> <tr> ... first element </tr> <tr> ... second element </tr> <tr> ... first element </tr> <tr> ... second element </tr> <tr> ... third element </tr> </table>
    And if the first element (and each of the others?) has a 2MB string in it, that's going to take a long time to convey to a browser (and the browser may have some trouble accommodating all that data).

    I'm not familiar with a module called "P3::util::HTML", but if its "doTableDetailRow()" function takes an array of table rows as its second parameter, I would expect that you should probably call it after the foreach loop, not inside the loop.

    You might also want to think about the user-interface / legibility / viewability issues that would arise from having 2MB of data in a single row (or cell?) of an html table... Maybe there's a better way to do whatever it is you are trying to do?

Re: having problem in displaying large size of variable on web page
by perlfan (Vicar) on Sep 27, 2007 at 13:51 UTC
    Even in CGI scripts, you should use strict; and use warnings;. This could help you right off the bad.

    Does this work if the contents of the variable are small? In other words, are you positive it is related the size of the variable and not something that you're doing incorrectly in the script? Just because it prints at the command line doesn't mean it'll come through when calling it through the web server.

    I also noticed that $retHashRef{$viewItem[0]} = $viewStr; should be $retHashRef->{$viewItem[0]} = $viewStr; ... unless $viewItem is itself an anonymous array ref, which would mean you'd have to use $viewItem->[0].

    We can't really help with out more code.
      Even in CGI scripts, ...

      I would rephrase that:

      Especially in CGI scripts, ...

      And I would add: Always do "perl -T -cw my_cgi_script" in a command-line shell before you make it runnable on a web server, to make sure it compiles with taint checks in effect.

      (update: a lot of taint checks can only be applied at runtime, and I'm not sure I can identify any compile-time taint checks, but your cgi script should have "-T" in the shebang line, and when that's true, a shell command line like  perl -cw my_script won't work.)

      Thanks for response.
      yes it does work with small string. I have updated my post and also posted portion of code that does display on browser.
        Thanks for the update. But I'm still a little confused about your code. You say that the last snippet produces the intended display for a small amount of data, so it seems like your problem arises when you try to display a large amount of data. I think that makes sense.

        So, one way to look for a solution is to figure out how to get the job done with less data being sent to the browser (and maybe with less data being handled by the server, too).

        As I said before, your "P3::util::HTML" module is unknown to the rest of us; if you don't want to start putting that code up for public review, that's okay, but you're on your own if that module turns out to be part of the problem. I noticed that there was a difference in how the two snippets use it:

        # original snippet (with the large amount of data, not working): foreach my $row (keys %$dbDDL) { push @rowArr, '<pre> ' . '<font size=2>' .$dbDDL->{$row} . '</font>' +. '</pre>' ; &P3::util::HTML::doTableDetailRow($altColor, @rowArr); } # update snippet (working with a small amount of data): foreach my $row (keys %$dbDDL) { &P3::util::HTML::doTableColAttributes(''); $altColor = !$altColor; my @rowArr; push @rowArr, '<pre> ' . '<font size=2>' .$dbDDL->{$row} . '</font +>' . '</pre>' ; &P3::util::HTML::doTableDetailRow($altColor, @rowArr); }
        The difference is that in the first snippet, @rows gets larger by one entry on each iteration, whereas in the second one, it's always a brand new array, with just one entry in it -- in effect, you could be passing a scalar (not an array) to "doTableDetailRow()".

        If the function really takes a "color" spec and an array (i.e. a list of strings) as its parameters, the list is either for cells on a row or for rows in a table. If it's supposed to take a list of cell values for one row, then the first snippet above is just wrong and will not display the data correctly -- and if you are handling 2 MB per entry in @row, it's disastrously wrong:

        <table> <!-- first iteration: --> <tr><td>... 2MB string </td></tr> <!-- second iteration: --> <tr><td>... 2MB string </td><td>another 2MB string</td><tr> <!-- and so on ... --> </table>

        For now, you are the only one in this discussion who can know the correct usage for that module. If you don't know, I hope for your sake that it's documented somewhere so you can RTFM.

        In the meantime, you should still look into figuring out what the user of this web service is supposed to accomplish, and see if you can figure out how to enable that without requiring the person to scan megs of data in a table on his browser window.

Re: having problem in displaying large size of variable on web page
by artist (Parson) on Sep 27, 2007 at 12:28 UTC
    We need more code. I don't see the print statement here. If you think that if variable is too big, take small value and try again.
    --Artist