1

I requested Walmart report API and the result would be returned zip file stream.Refer to the API documents,it gives an example to realize it with Java code as the following below:

if (response.getStatus() == Response.Status.OK.getStatusCode() && response.hasEntity()) {
  InputStream inputStream = (InputStream)response.getEntity();
  try {
    String header = response.getHeaderString("Content-Disposition");
    if(header != null && !("").equals(header)) {
      if(header.contains("filename")){
        //header value will be something like:
        //attachment; filename=10000000354_2016-01-15T23:09:54.438+0000.zip
        int length = header.length();
        String fileName = header.substring(header.indexOf("filename="),length);
        System.out.println("filenameText " + fileName);
        String [] str = fileName.split("=");
        System.out.println("fileName: " + str[1]);
        //replace "/Users/anauti1/Documents/" below with your values
        File reportFile = new File("/Users/anauti1/Documents/" + str[1].toString());
        OutputStream outStream = new FileOutputStream(reportFile);
        byte[] buffer = new byte[8 * 1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
          outStream.write(buffer, 0, bytesRead);
        }
        IOUtils.closeQuietly(inputStream);
        IOUtils.closeQuietly(outStream);
      }
    }
  }
  catch (Exception ex){
    System.out.print("Exception: " + ex.getMessage());
  }
}

However,if I use php like:

try {
                        $header = $resultInfo->getHeader('Content-Disposition');
                        if (!empty($header)) {
                            if (strpos($header, 'filename') !== false) {
                                $filename = substr($header, strpos($header, 'filename'));
                                $str = explode('=', $filename);
                                $body = $resultInfo->getBody();
                                $fp = fopen(storage_path("csv/{$str[1]}"), 'w');
                                fwrite($fp, $body);
                                fclose($fp);
                            }
                        }
                    } catch (\Exception $e) {
                        echo $e->getMessage();
                    }

It would download zip file but the file data is corrupt.It maybe such a reason like the byte stream is transfered by using Java code.It's the problem about how to transform the bytes stream.Could you help me? By th way,I have cut parts of the stream as the following below:

b"PK\x03\x04\x14\x00\x00\x00\x08\x00\x10`‚OI^\x07RÒƒ\x04\x00Óo\x10\x004\x00\x00\x00ItemReport_10001023965_2019-12-02T115111.5040000.csvì½YsÛÈ–.ú~#î\x7F`ì‡>

Headers like this:

-headers: array:11 [
            "accept-ranges" => array:1 [
              0 => "bytes"
            ]
            "content-disposition" => array:1 [
              0 => "attachment; filename=ItemReport_10001023965_2019-12-02T115111.5040000.zip"
            ]
            "content-type" => array:1 [
              0 => "application/zip"
            ]
            "x-tb" => array:1 [
              0 => "0"
            ]
            "expires" => array:1 [
              0 => "Wed, 04 Dec 2019 02:33:20 GMT"
            ]
            "cache-control" => array:1 [
              0 => "max-age=0, no-cache, no-store"
            ]
            "pragma" => array:1 [
              0 => "no-cache"
            ]
            "date" => array:1 [
              0 => "Wed, 04 Dec 2019 02:33:20 GMT"
            ]
            "transfer-encoding" => array:1 [
              0 => "chunked"
            ]
            "connection" => array:2 [
              0 => "keep-alive"
              1 => "Transfer-Encoding"
            ]
            "set-cookie" => array:1 [
              0 => "TS0d138f181a7bb55a8f02b54ee05b24ba9b4832fa32c8b0a9c4cb8592e5d1e4d02765d16ec77313d435d3ade8; Path=/; Secure"
            ]
          ]
          -headerNames: array:11 [
            "accept-ranges" => "Accept-Ranges"
            "content-disposition" => "Content-Disposition"
            "content-type" => "Content-Type"
            "x-tb" => "X-Tb"
            "expires" => "Expires"
            "cache-control" => "Cache-Control"
            "pragma" => "Pragma"
            "date" => "Date"
            "transfer-encoding" => "Transfer-Encoding"
            "connection" => "Connection"
            "set-cookie" => "Set-Cookie"
          ]

I just found that the transfer-encoding is chuncked.I'm not sure it's this problem?

Joephper
  • 25
  • 5

2 Answers2

0

It seems Json Encoded and you Must Decode it with json in php script so: json_decode(string,array) string = your gathered encoded response. array = True if you want array of result data.

2- use header('Content-Type: application/json') (this header most useful before sending or recieving response)

3 -Error handling : json_last_error() json_last_error_msg()

try {
                        $header = $resultInfo->getHeader('Content-Disposition');
                        if (!empty($header)) {
                            if (strpos($header, 'filename') !== false) {
                                $filename = substr($header, strpos($header, 'filename'));
                                $str = explode('=', $filename);
                                $body = $resultInfo->getBody();
                                $fp = fopen(storage_path("csv/{$str[1]}"), 'w');
                                ##uncomment below line if response not valid may help you.                            
                                # header('Content-Type: application/json');
                                $dbody = json_decode($body,true);
                                fwrite($fp, $dbody);
                                fclose($fp);
                            }
                        }
                    } catch (\Exception $e) {
                        echo $e->getMessage();
                    }

Hope to be helpful

Behnam Alavi
  • 127
  • 1
  • 4
  • Nope! It's bytes stream not json.Tx ur help! – Joephper Dec 04 '19 at 11:29
  • skip json_decode and try using var_dump() then post result. – Behnam Alavi Dec 04 '19 at 11:38
  • for better help you must post complete response .use online decoders with full response to find text format. ex : https://conv.darkbyte.ru – Behnam Alavi Dec 04 '19 at 11:53
  • It 's too long and I have post parts of the result like:b"PK\x03\x04\x14\x00\x00\x00\x08\x00\x10`‚OI^\x07RÒƒ\x04\x00Óo\x10\x004\x00\x00\x00ItemReport_10001023965_2019-12-02T115111.5040000.csvì½YsÛÈ–.ú~#î\x7F`ì‡> By the way,I have added the headers.The api call return a zip file – Joephper Dec 04 '19 at 11:53
  • using gzdecode() for decoding zip files.i can't test because you must pass full zip data to function and before this you must get len of zip data as follow : $len = strlen($data); $out=gzdecode($data,$len); Sometimes you must use more decoding together to achieve true result search walmart documents is best way.example of divided decoding : gzdecode(hex2bin(base64_decode($data))),$len); – Behnam Alavi Dec 04 '19 at 15:21
  • This PHP functions may help:\n zlib_get_coding_type($data) ## for finding compressed output zip method #####gzuncompress($data); ##### zlib_decode ( string $data [, string $max_decoded_len ] ) # – Behnam Alavi Dec 04 '19 at 15:30
  • Ok! Thank you! I'll try it! – Joephper Dec 05 '19 at 01:32
0

Did you resolve the issue? The below simple code worked for me

    $fp = fopen('/your path where you store the zip file/'.$filename, 'w+'); 
    if ($fp == FALSE){ 
      print "File not opened<br>"; 
      exit; 
    }
    fwrite($fp, $response);
    fclose($fp);

$response is the body of API response, which will be unreadable format $filename zip filename got from the header.

Deepak
  • 2,660
  • 2
  • 8
  • 23
  • Yep! I find it's not my code's wrong.It's just file's wrong.I have some different kinds of store.Emmm...some can open the file,Others call a data corrupt error. – Joephper Apr 22 '21 at 02:10