Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]10168[/thread]

ERR: reconstitute blessed object



<< >> 6 Einträge, 1 Seite
gluelangua
 2007-08-22 12:48
#98507 #98507
User since
2007-08-22
3 Artikel
BenutzerIn
[default_avatar]
Hallo Community,

ich schreibe derzeit an einer Software, die unter anderem den Benutzern den Upload von Bild- und Textdateien, sowie das Ausfüllen einiger Formularfelder ermöglicht (es geht um das "Anlegen" von Experimentdaten aus einem Genlabor).

Das Script nutzt CGI, CGI::SESSION und schickt die POST-Parameter an sich selbst.

Nun habe ich folgendes Problem:

Code (perl): (dl )
1
2
3
4
5
6
7
8
sub newMap {
        my ($dbid,$dbsname,$dblname,... etc.etc
        my $obj = {
                dbmapid => $dbid,
                dbmapshortname => $dbsname,
                dbmaplongname => $dblname,
                ...
                ...



Dieses Objekt wird durch das Klicken eines Buttons erzeugt und die entsprechenden Formulardaten dort eingetragen. Anschließend wird dieses Objekt in ein Array hinterlegt und die Referenz in der Session gespeichert.

Dieses Verfahren funktioniert solange gut, bis die cgi->filefields ins Spiel kommen. Dann kann man zwar noch einmal ein Objekt erzeugen, danach aber nicht wieder. Der Grund ist folgender:

Wenn man sich den Inhalt des Objektes mit DATA::DUMPER ansieht, dann findet man in den FileField-Hashes folgendes:


Code (perl): (dl )
1
2
3
'dbmapimage' => bless( \*{'Fh::fh00001blablabla.jpg'}, 'Fh' )
'dbmapthumb' => bless( \*{'Fh::fh00002blablablawasanders.jpg'}, 'Fh' )
'dbmapdatafile' => bless( \*{'Fh::fh00003blablabla.txt'}, 'Fh' )


Offensichtlich wird hier nicht nur der Dateiname von den Filefields zurückgegeben, sondern eine Referenz zu einem Typeglob-Objekt (Referenzen zu Filehandles werden durch Referenzen zu einem Typeglob erzeugt). Das "im Prinzip" ein Fh zurückgeben wird, ist kein Problem und durchaus auch erwünscht.

Der Upload funktioniert aber nur EINMALIG.

Wenn ich dann aber ein weiteres Objekt erzeugen will (das Formular ist dasselbe), dann kriege ich folgende Fehlermeldung:
Code: (dl )
1
2
Do not know how to reconstitute blessed object of base 
type GLOB at /usr/share/perl5/CGI/Session.pm line 687


Ein bißchen Schnüffeln brachte folgendes in der CGI::SESSION::SERIALIZE::DEFAULT zutage

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
sub __scan {
    for (@_) {
        if (blessed $_) {
            if (overload::Overloaded($_)) {
                my $r = reftype $_;
                if ($r eq "HASH") {
                    $_ = bless { %$_ }, ref $_
                } elsif ($r eq "ARRAY") {
                    $_ = bless [ @$_ ], ref $_
                } elsif ($r eq "SCALAR" || $r eq "REF") {
                    $_ = bless \do{my $o = $$_},ref $_
                } else {
                    croak "Do not know how to reconstitute blessed object of base type $r";
                }
            } else {
                bless $_, ref $_
            }
        }
    }
}


Dieser Codeabschnitt erklärt gut, warum der Vorgang nur einmal funktioniert: Zunächst ist der Fh !blessed und er wird geblesst (else-Fall). Beim zweiten Durchgang durch das Formular findet er offensichtlich nach dem POST ein bereits geblesstes Objekt (vermutlich drei, für jedes FileField der ersten Eingabe) und es kommt zu der in der ($r eq else) stehenden Fehlermeldung.

Daher ist meine Frage: Wie kriege ich das Formular in dem Sinne gelöscht, das die Uploadfields nach dem Upload wieder "wie neu", also "clean" ohne blessed-Objekte sind? Wie zerstöre ich das Objekt dahinter (DESTROY?)?.

Vielen Dank für Eure Hilfe!


PS: Noch folgende, wirklich nicht böse gemeinten, Anmerkung:
Bitte keinen Verweis auf irgendwelche Standard-Tutorials und Upload.cgi's -> über dieses Stadium bin ich etwas hinaus ;)
nepos
 2007-08-22 14:54
#98513 #98513
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
So gut kenne ich mich mit CGI::Session und Co nicht aus, aber könntest du eventuell nicht versuchen, einen anderen Serializer (Storable oder FreezeThaw) zu benutzen?
Oder musst du diese Infos für den Upload überhaupt in der Session halten bzw. kannst du den nicht einfach aus der Session entfernen, wenn der Upload durchgeführt wurde?
Struppi
 2007-08-22 15:47
#98514 #98514
User since
2006-02-17
628 Artikel
BenutzerIn
[Homepage]
user image
ich bin nicht 100% sicher was du da machst.
Ich nehme an du willst den Filhandle der hochgeladenen Dateien in den Sessions speichern. Das düfte nicht gehen, zumal dieser bei einem CGI Upload sowieso temporär sein sollte. D.h. du musst diese Datei erst richtig speichern und dann z.b. den Namen der Datei in deiner Session speichern, nicht den filehandle.
gluelangua
 2007-08-22 16:45
#98517 #98517
User since
2007-08-22
3 Artikel
BenutzerIn
[default_avatar]
@nepos
Die habe ich bereits beide versucht, das Phänomen bleibt gleich...

@Struppi
Den Filehandle will ich nicht speichern. Selbst wenn nach dem 'Submit' erst die Files gelesen und gespeichert werden (was wie gesagt einmalig funktioniert), erfolgt beim nächsten 'Submit' trotzdem der Fehler. Offensichtlich versucht er die Typeglobs nochmal zu senden, was aufgrund des Typs GLOB (also nicht HASH, ARRAY, SCALAR) fehlschlägt. Würde er die Dinger NACH dem Upload vernichten, dann wäre alles gut.

Woran unterscheidet Perl, wann er den Filename zurückgibt und wann die Referenz auf den Filehandler? Denn

Code (perl): (dl )
print $cgi->param('dbmapimage');


liefert

Code: (dl )
"meinpicture.jpg"


aber

Code (perl): (dl )
1
2
3
4
5
6
7
8
sub newMap {
         my ($dbpic...
         my $obj = {
                 dbmapimage => $dbpic,
                 ...
                 ...
         }
}


mit dem Aufruf

Code (perl): (dl )
my $object = newMap($cgi->param('dbmapimage'), ...)

liefert
Code: (dl )
'dbmapimage' => bless( \*{'Fh::fh00001meinpicture.jpg'}, 'Fh' )
renee
 2007-08-22 16:52
#98519 #98519
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Das passiert durch das "Stringifizieren"... Probier mal my $object = newMap($cgi->param('dbmapimage') . '' , ...)
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
gluelangua
 2007-08-26 13:44
#98677 #98677
User since
2007-08-22
3 Artikel
BenutzerIn
[default_avatar]
@renee
Natürlich ;) Das funktioniert.


@All

Das Problem hat sich folgendermaßen lösen lassen:

1. Der CGI->param wird zerstört.
Code (perl): (dl )
DESTROY($co->param('blablub'));


2. Der Session->param wird geleert
Code (perl): (dl )
$session->param('blablub', '');


3. Der Rückgabewert wird "stringfiziert" gespeichert
Code (perl): (dl )
1
2
3
4
5
6
push (@{$uploadlist}, 
        newMap(
                $session->param('dbmapid').'',
                ...
        )
);


Zu 1:
http://www.unix.org.ua/orelly/perl/cookbook/ch13_03.htm

Vielen Dank für Eure Antworten!
<< >> 6 Einträge, 1 Seite



View all threads created 2007-08-22 12:48.