3

I am trying to find out the exact length of a string using strlen() in php 5.2. The string ($data) contains '\t' and '\n'.

echo strlen($data);

Code:

    // fetch table header
      $header = '';
      while ($fieldData = $result->fetch_field()) {
        $header .= $fieldData->name . "\t";
      }

      // fetch data each row, store on tabular row data
      while ($row = $result->fetch_assoc()) {
        $line = '';
        foreach($row as $value){
          if(!isset($value) || $value == ""){
            $value = "\t";
          }else{
            // important to escape any quotes to preserve them in the data.
            $value = str_replace('"', '""', $value);
            // needed to encapsulate data in quotes because some data might be multi line.
            // the good news is that numbers remain numbers in Excel even though quoted.
            $value = '"' . $value . '"' . "\t";
          }

          $line .= $value;
        }
        $data .= trim($line)."\n";
      }

      // this line is needed because returns embedded in the data have "\r"
      // and this looks like a "box character" in Excel
      $data = str_replace("\r", "", $data);

      // Nice to let someone know that the search came up empty.
      // Otherwise only the column name headers will be output to Excel.
      if ($data == "") {
        $data = "\nno matching records found\n";
      }

      // create table header showing to download a xls (excel) file
      header("Content-type: application/octet-stream");
      header("Content-Disposition: attachment; filename=$export_filename");
      header("Cache-Control: public");
      header("Content-length: " . strlen($data); // tells file size
      header("Pragma: no-cache");
      header("Expires: 0");

  // output data
  echo $header."\n".$data;

This does not return the exact length (its less than the actual length). Please advice.

Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
kobra
  • 4,853
  • 10
  • 32
  • 33
  • 2
    What is the string, what is the expected length and what is the actual length that is echoed? – BoltClock Aug 24 '10 at 22:47
  • 2
    You should not assume strlen() has a bug. What is the length you get returned ? What did you excpect ? – nos Aug 24 '10 at 22:48
  • I am trying to save data from mysql table as Excel file. I always get some characters of last record missing. If I do header("Content-length: " . (strlen($data) + 148)); in place of header("Content-length: " . strlen($data)); I get the correct result. – kobra Aug 24 '10 at 22:51
  • @nos I am adding \t and \n, so I am sure its there in the string. – kobra Aug 24 '10 at 22:52
  • was that string created with single quotes, e.g. `'\tfoo\nbar'`? – Gordon Aug 24 '10 at 22:53
  • @kobra: what is the output of `echo strlen($data)` that you see, and what were you expecting? – BoltClock Aug 24 '10 at 22:58
  • I don't think strlen is broken. Please show the entire (relevant) code. – mvds Aug 24 '10 at 22:59
  • I am in no way suggesting strlen is broken. I just need solution to my problem. – kobra Aug 24 '10 at 23:01
  • 3
    This is not excel, this is CSV. but on topic. *show the entire code* please, there is not even a `strlen()` in your question now! – mvds Aug 24 '10 at 23:02
  • 1
    You should set `$data='';` for starters or you will get a nice warning in that CSV (might your warnings add up to 148 bytes? have you looked at the csv?) – mvds Aug 24 '10 at 23:03
  • like, when saved to disk before MS laid its hands on it? and viewed with `less`, `notepad`, `hexdump` or other basic viewer? – mvds Aug 24 '10 at 23:04
  • And please tidy up, add `\t` in one place, like `$line .= $value."\t";` – mvds Aug 24 '10 at 23:07
  • Any particular reason you my question got -1. – kobra Aug 24 '10 at 23:13

5 Answers5

14

You are telling the user agent to expect strlen($data) and then actually sending $header."\n".$data! Try something like this at the end of your code...

  $output=$header."\n".$data;

  // create table header showing to download a xls (excel) file
  header("Content-type: application/octet-stream");
  header("Content-Disposition: attachment; filename=$export_filename");
  header("Cache-Control: public");
  header("Content-length: " . strlen($output); // tells file size
  header("Pragma: no-cache");
  header("Expires: 0");

  // output data
  echo $output;
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
2

strlen returns the correct answer:

echo strlen("1\n2\t3");

// prints 5

You will need to examine your input more carefully.

webbiedave
  • 48,414
  • 8
  • 88
  • 101
  • I think when I save the data in Excel format, it translates \n and \t (non-printing characters. So if the tab size is 4 the above should result in length of 8. I think thats the problem. – kobra Aug 24 '10 at 23:04
  • @kobra: each tab is **always** 1 character. I don't think Excel ever messes with your tab characters. – BoltClock Aug 24 '10 at 23:05
  • this worked for me: header('Content-Length: '. strlen($data)); – Joeme Jul 04 '17 at 01:40
2

The content-length header does NOT include the length of the headers plus the body of the response.

Content-Length: The length of the response body in octets (8-bit bytes)

Just FYI since the variables used in the "answer" are header + data. Do not be misled.

j0k
  • 22,600
  • 28
  • 79
  • 90
mooyah
  • 76
  • 3
  • The $header variable in his example is not the HTTP header. Unless of course you cautioned us all not to think he's trying to output the HTTP header with the data, in which case... nothing to see here. – Micke Jan 06 '16 at 17:18
1

You echo both $header and $data, but you only set Content-Length to the size of $data.

If $header contains additional HTTP-headers, you should output $header using header(). Otherwise, you should set Content-Length to strlen($header."\n".$data).

Muhammad Hassaan
  • 7,296
  • 6
  • 30
  • 50
Micke
  • 599
  • 4
  • 8
1

Before getting length of string, delete '\t' and '\n' symbols from $data with str_replace or with other function like that if strlen() really has bug (I haven't checked that).

good_evening
  • 21,085
  • 65
  • 193
  • 298