I have a script that is meant to allow a user to upload files of type DOC, DOCX, PDF and TXT. Files do get uploaded, albeit without line breaks. So for instance, a TXT files like this:
//////////
THIS IS A TEXT FILE
//////////
gets downloaded back as:
//////////THIS IS A TEXT FILE//////////
Now this is not such a "big" issue with text files but this loss of line breaks completely corrupts PDF, DOC and DOCX types.
Again, a PDF viewed in Notepad originally looks like this:
%PDF-1.5
%µµµµ
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-US) /StructTreeRoot 10 0 R/MarkInfo<</Marked true>>>>
endobj
2 0 obj
....
However, after uploading and then downloading, it looks like one long string with some characters gone missing:
%PDF-1.5%µµµµ1 0 obj<>>>endobj2 0 obj
Hence, when opening the file in Adobe PDF reader, it says it is corrupted.
This is an excerpt of the PHP script I am using to upload the file:
$_POST['request_id'] = $_POST['rid'];
$tmpName = $_FILES['exam_file']['tmp_name'];
$_POST['name'] = $_FILES['exam_file']['name'];
$_POST['type'] = $_FILES['exam_file']['type'];
$_POST['size'] = $_FILES['exam_file']['size'];
//File types allowed are PDF, DOC, DOCX, TXT
if ( ( $_POST['type'] == "application/pdf") || ($_POST['type'] == "application/msword") || ($_POST['type'] == "application/vnd.openxmlformats-officedocument.wordprocessingml.document") || ($_POST['type'] == "text/plain") ){
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
fclose($fp);
$file_id = $model -> addFiles($_POST, $content);
}
The function addFiles() in $model is as follows:
function addFiles($data, $file){
$table = 'faculty_files';
$data = parent::clean($data);
$keys = array('request_id', 'name', 'type', 'size', 'content');
$data = parent::cleanAndPick( $keys, $data );
$data['content'] = $file;
$data['faculty_user_id'] = $_SESSION['user_details']['id'];
$data['inserted_on'] = date('Y-m-d H:i:s');
parent::insert( $table, $data );
return mysql_insert_id();
}
parent::insert()
just takes all the relvant details such as table name and fields and puts them into a SQL statement.
This is the function parent::clean()
although $file
is not being run through it:
public function clean($data = NULL){
$data = str_replace("
", "", $data);
$data = str_replace("", "", $data);
$data = stripslashes($data);
return mysql_real_escape_string($data);
}
Function parent::cleanAndPick()
public function cleanAndPick($keys, $data = NULL) {
$clean = array();
foreach ($keys as $key) {
if (array_key_exists($key, $data))
$clean[$key] = $this -> clean($data[$key]);
}
return $clean;
}
Function parent::insert()
protected function insert($table, $data ) {
//Build sql
$data = $this -> clean($data);
$sql = "INSERT INTO " . $this -> clean($table);
$sql .= " (" . implode(",", array_keys($data)) . ") VALUES (";
foreach ($data as $value)
$sql .= ($value == NULL ? "NULL," : "'" . $value . "',");
$sql = substr($sql, 0, -1) . ")";
return $this -> query($sql);
}
This is the PHP script I am using to download the file:
$file = $model -> retrieveFile($_POST['fid']);
header("Content-length: " . $file[0]['size'] . "");
header("Content-type: " . $file[0]['type'] . "");
header("Content-Disposition:attachment; filename=" . $file[0]['name'] . "");
print $file[0]['content'];
I have no idea what is causing this problem. I would appreciate any input!
EDIT: Someone had a similar problem on the PHP forum. An excerpt:
I have been trying unsuccessfully to upload and read a Mac OS file on a Linux server. Lots of records show up a just one big using only the following:
<?php $fhandle = fopen($file, 'r'); ?> or <?php $fhandle =
> fopen($file, 'rb'); ?>
It does work, however, this way:
> <?php ini_set('auto_detect_line_endings', TRUE); $fhandle =
> fopen($file, 'r'); ?>
I did try this and it didn't work for me.
Use fopen($tmpName, 'rb');
if you don't want any change to its contents.
And then this:
protected function insert($table, $data ) {
//Build sql
$data = $this -> clean($data); //<---- here......