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

I am receiving a response in HTTP::Response, it is MIME, first part is XML, and second part is a Zip file. I need to extract the Zip file. I've tried to use...
XML::Parser
MIME::Parser
Email::MIME
And ->parts to get the attachment.

Here is a sample of the response; I have removed some private info, and the attached zip file will be mangled. I am receiving the file into memory, and I do save the message to a (binmode) binary file.

The goal is to Parse the XML and save the Zip file.

--MIMEBoundary_f43b637d78a6e09fe8ae5ffa2b682c98c3f079bc2615c0b6 Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: binary Content-ID: <0.843b637d78a6e09fe8ae5ffa2b682c98c3f079bc2615c0b6@apache +.org> <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv= +"http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><ns1:MeFH +eader xmlns:ns1="http://www.....xsd"><ns1:MessageID>51331201523500000 +932R</ns1:MessageID><ns1:RelatesTo>51331201523500000932</ns1:RelatesT +o><ns1:Action>SendSubmissions</ns1:Action><ns1:MessageTs>2015-10-04T2 +3:20:09Z</ns1:MessageTs><ns1:ETIN>55555</ns1:ETIN><ns1:SessionKeyCd>Y +</ns1:SessionKeyCd><ns1:TestCd>T</ns1:TestCd><ns1:AppSysID>59999999</ +ns1:AppSysID><ns1:WSDLVersionNum>9.5</ns1:WSDLVersionNum></ns1:MeFHea +der><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01 +/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.o +asis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd +"> <wsu:Timestamp wsu:Id=""> <wsu:Created /> <wsu:Expires /> </wsu:Timestamp> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" Ass +ertionID="id-28be86bbae26a90625737084a2d89e294184e711" IssueInstant=" +2015-10-05T06:24:38.896Z" Issuer="http://www.forumsys.com/sentry" Maj +orVersion="1" MinorVersion="1"> <saml:Conditions NotBefore="" NotOnOrAfter="2015-10-05T16:24:38.896Z"> <saml:DoNotCacheCondition /> </saml:Conditions> <saml:AuthenticationStatement AuthenticationInstant="2015-10-05T06:24: +38.896Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:passwor +d"> <saml:Subject> <saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format +:X509SubjectName">UID=username,OU=System,OU=External, OU=Internal,OU= +Department, O=U.S.A.,C=US</saml:NameIdentifier> <saml:SubjectConfirmation> <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches +</saml:ConfirmationMethod> </saml:SubjectConfirmation> </saml:Subject> <saml:SubjectLocality IPAddress="192.168.182.20" /> </saml:AuthenticationStatement> <saml:AttributeStatement> <saml:Subject> <saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format +:X509SubjectName">UID=username,OU=System,OU=External, OU=Internal,OU= +Department, O=U.S.A.,C=US</saml:NameIdentifier> <saml:SubjectConfirmation> <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches +</saml:ConfirmationMethod> </saml:SubjectConfirmation> </saml:Subject> <saml:Attribute AttributeName="SMSESSION" AttributeNamespace="http://w +ww.forumsys.com/sentry"> <saml:AttributeValue>O1UlDahKHbTjPt2Q/ZLTjNYs+...... Z7fLDzav6OW7g6xqsNRrBam3cNvDiLxpCE=</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> <wsse:UsernameToken> <wsse:Username>59999999</wsse:Username> </wsse:UsernameToken> </wsse:Security></soapenv:Header><soapenv:Body><ns3:SendResponse xmlns +:ns3="http://www......xsd" /></soapenv:Body></soapenv:Envelope> --MIMEBoundary_f43b637d78a6e09fe8ae5ffa2b682c98c3f079bc2615c0b6 Content-Type: application/octet-stream Content-Transfer-Encoding: binary Content-ID: <urn:uuid:D9F0A4BBD2EBF816AD1444026286314> PK UlJYhL\)^@ <.Pg3O't:U GΕ.btNnRf2e3xچa +ZuU`o>c›GfsAWQ Z/wM'ԈM00p +!d --MIMEBoundary_f43b637d78a6e09fe8ae5ffa2b682c98c3f079bc2615c0b6--
Snippet:
my $request = HTTP::Request->new(POST => 'https://<www>/Send'); $request->content($xmldat); my $response = $userAgent->request($request); my $xmlin = $response->content(); open(F, "> /..../attach.eml\0") ; binmode(F); print F $xmlin; close(F); my $parser = Email::MIME->new($xmlin); my @parts = $parser->parts; for my $part (@parts) { my $content_type = $part->content_type; my $content = $part->body; print "\n$content_type :: $content\n"; }

Replies are listed 'Best First'.
Re: HTTP::Response parse and save attached zip file.
by GotToBTru (Prior) on Oct 05, 2015 at 18:54 UTC

    I would start by testing the following statement for success or failure:

     my $parser = Email::MIME->new($response->content);
    Dum Spiro Spero

      GotToBTru:
      I don't know of a test such as is_success, however, there is data in the object. I'm having trouble separating the parts, the second part is appearing in the message as a single part message.
      Am I using the right module for the job, if not, what is recommended?

        So, what happened when you ran the above code?

        What was the result stored in $parser?

        Was there output? Was an error raised?

Re: HTTP::Response parse and save attached zip file.
by thomas895 (Deacon) on Oct 05, 2015 at 18:45 UTC

    Please move the code into your question, it makes it easier to read while responding.

    When you run that code, what happens? Do you get an error message? What does it say? How have you tried to fix it?
    If you don't get an error, how does the result differ from what you expect? Does your zip library of choice support extraction from memory?

    -Thomas
    "Excuse me for butting in, but I'm interrupt-driven..."

      Code moved to question per thomas895, thank you.
      The data shown (GotToBTru), is the response.

      What module would best parse the content to extract the attached binary Zip file?

      Good questions thomas895;
      When you run that code, what happens?
      I can see the data (shown in question). But I can't get parts to give me the second multipart message (mime) which contains the Zip file.
      Do you get an error message?
      No error message that I am aware of (apache log, or in browser)
      What does it say? N/A
      How have you tried to fix it?
      I can get my script to display the response data (shown in question), saved as binary, when I open the response mime file in my thunderbird email, the zip file is there, but it is corrupt (wrong size too).
      If you don't get an error, how does the result differ from what you expect?
      I cant get to the Zip file. I want to extract it and save it to a file.
      Does your zip library of choice support extraction from memory?
      I dont have one yet... I am considering Archive::Zip.

      Thanks for your replies. :)

        I was able to get the zip file out of my response data. Although I'm very happy about that, I'm not sure I have a full understanding of why it wouldn't show when I parsed the data. Thank you Dumper! :) $zipfile in the code below did have my zip file intact...I unzipped and had good data. Time for a coffee break and contemplation!! :) :)

        my $parser = MIME::Parser->new(); $parser->output_to_core(1); my $ref = $parser->parse_data(\$xmltrans); my $zipfile = $ref->{ME_Parts}[0]{ME_Bodyhandle}{MBS_Data};
Re: HTTP::Response parse and save attached zip file.
by sharprez (Novice) on Oct 05, 2015 at 15:38 UTC

    Below is some of the code

    my $request = HTTP::Request->new(POST => 'https://<www>/Send'); $request->content($xmldat); my $response = $userAgent->request($request); my $xmlin = $response->content(); open(F, "> /..../attach.eml\0") ; binmode(F); print F $xmlin; close(F); my $parser = Email::MIME->new($response->content); my @parts = $parser->parts; for my $part (@parts) { my $content_type = $part->content_type; my $content = $part->body; print "\n$content_type :: $content\n"; }