编辑:downl.php
嗨Royal Bg。
我不知道该怎么感谢你。但是你的代码似乎很好但很难让我理解,所以我仍然推荐下载页面....
我的downl.php页面如下所示:
require('staff.php'); // User controll
if(($thisuser->getGroupId() != 4)){
header('Location: index.php');
require('index.php');
exit;
}
//收到学生文件ID,学生ID和朗姆酒ID(课程ID)来自rum_st.php
if (isset($_GET['f-id']) && is_numeric($_GET['f-id']) &&
$_GET['f-id'] >= 1 && isset($_GET['s-id']) && is_numeric($_GET['s-id']) &&
$_GET['s-id'] >= 1 && isset($_GET['r-id']) && is_numeric($_GET['r-id']) && $_GET['r-id'] >= 1 ) {
$file_id_s = $_GET['f-id'];
$stud_id = $_GET['s-id'];
$rums_id = $_GET['r-id'];
$sql = " SELECT t.ticket_id, t.ticketID, t.staff_id, t.subject, r.rums_id, r.staff_id, r.rumsname ".
" f.file1_id, f.rums_id, f.ticket_id, f.file_name, f.staff_id, f.filetype, f.filesize, f.created, f.dept_id ". // dept_id means class_id or grade_id
" sc.school_id, sc.school_name ".
" FROM ice_cust_ticket t ".
" INNER JOIN ice_file f ON f.ticket_id = t.ticket_id ".
" INNER JOIN ice_rums r ON r.rums_id = f.rums_id ".
" INNER JOIN ice_cust_school sc ON sc.school_id = f.dept_id ". // school means class or grade
" WHERE f.rums_id = ".$rums_id." " .
" ORDER by f.created ";
$res = mysql_query($sql);
while ($row = mysql_fetch_array($res)) {
$filename = htmlspecialchars($row['file_name']);
$fileID = $row['file1_id'];
$rums_id3 = $row['rums_id'];
$dept_id = $row['dept_id']; // Class id if he/she is from class 4 .. 5 ..
$dept_id3 = explode(',', $dept_id);
if(in_array($thisuser->getdeptID(), $dept_id3)){
$rumsname = htmlentities($row['rumsname'], ENT_QUOTES, "UTF-8");
$file_name = htmlentities($row['file_name'], ENT_QUOTES, "UTF-8");
$teacher_id = $row['staff_id'];
// Teacher file
// $target_path = "rums/".$teacher_id."/".$rumsname."/".$file_name."/";
// Student file
$target_path_st = "rums/".$teacher_id."/".$rumsname."/".$file_name."/".$thisuser->getId()."/";
$sql_st_file = " SELECT * FROM ice_student_file WHERE file_id = ".$fileID." AND stud_id = ".$thisuser->getId()." ";
$res_st = mysql_query($sql_st_file);
$row_st = mysql_fetch_array($res_st);
$file = $row_st['file_name'];
$result = $row_st['result'];
$opinion = $row_st['opinion'];
// with link like target=_blank......
//$url = '<a href="'.$target_path_st.$file.'" target="_blank id="attached-file-link" style="text-decoration:none;">'.$file.'</a>';
// or without link
$url = '<a href="'.$target_path_st.$file.'">'.$file.'</a>';
// this give me the same problem.. shows the link where it is and I have to click to download
//echo $url;
// echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.'">'; // And This give me Error 403
// The question is where to put the headers and what to write on headers...
}
}
}
我正在用PHP为我的学校创建一个简单的系统。
教师在名为rums的文件夹中创建自己的课程
他们可以将这些课程提供给不同的课程。
例如,Linda老师创建了名为Biology的课程,并提供了对4级和5级的访问。它运行正常。
所以这将是localhost \ my \ my2 \ rums \ ...并在这里创建名为Biology的文件夹。但是在Biology之前,它还创建了一个文件夹,用户ID为nr,例如Linda用户ID为91只是为了防止与其他教师课程名称发生冲突。所以它会像下面这样:
localhost \ my \ my2 \ rums \ 91 \ Biology
Linda将可下载的文件(如docx和pdf文件)插入到此Biology文件夹中,来自4级和5级的学生可以下载。然后他们可以将不同的文件插入Linda到这个文件夹作为对作业的回应,这样她也可以下载学生文件。
这个php页面只能访问那些有权限的类。它工作正常,他们可以看到教师档案。
所以,如果学生我们说她的名字是Sarah,从4级插入文件到这个文件夹,他就能看到她自己插入的文件..而且它工作正常。没有其他人可以看到它。
从数据库我得到这些文件:
$target_path_teacher_file = "rums/".$teacher_id."/".$rumsname."/".$file_name."/";
$target_path_student_file = "rums/".$teacher_id."/".$rumsname."/".$file_name."/".$thisuser->getId
()."/";
要在桌子上展示我打印出来就像这样:
<td><center><?php print '<a href="'.$ target_path_teacher_file.$filename.'" target="_blank id="attached-file-link" style="text-decoration:none;">'.$filename.'</a>'; ?></center></td>
<td><center><?php print '<a href="'.$target_path_student_file.$file.'" target="_blank id="attached-file-link" style="text-decoration:none;">'.$file.'</a>'; ?></center></td>
但是在文件上你可以看到文件所在的空洞链接..如果大卫复制此链接并发送给其他人并通过网络浏览器过去,那么即使他们也可以下载他的文件和教师文件。
亲爱的人们......我的问题是如何防止其他已注册的人员下载,除Sarah外没有注册人员?我尝试使用.htaccess文件,但没有工作。
任何帮助你都会非常感激。
/乔纳斯
答案 0 :(得分:1)
我可以想象的第一眼看到的解决方案是将文件存储到非公共目录中:
即:
www/private/assignment.docx
当您验证用户凭据时,即Sarah
来自第4类并且其中一个请求该文件,请在后台运行一个脚本,该脚本将该文件的临时副本复制到具有不同名称的公共目录,即
www/public/sarah-homework-2014-04-20.docx
和/或也没有给他们机会知道文件的来源。或者至少让它变得更难。您不需要直接链接。通过会话download.php
和user_id
发送您的链接指向file_id
。
如果此user_id具有权限并从download.php
直接开始下载
您也不能允许下载,但会向他们发送带有该文件的电子邮件。在成功验证用户来自允许的类之后,可以使用附加的文件接收电子邮件。
我能想象的所有其他方式都是文件系统权限,.htaccess等等。
关于评论中的问题。
我建议通过设置正确的内容类型标题来使用下载。 将文件作为资源打开,然后强制下载。
一个简单的用户类,你有userId,所以你可以检查权限(我不会在这里检查权限,它只是一个例子)
class User {
private $_id;
public function setId($id) { $this->_id = $id; }
public function getId() { return $this->_id; }
}
收到file_id后获取文件信息的简单类;
class File {
private $_directory;
private $_filename;
private $_id;
public function setId($file_id) {
$this->_id = $file_id;
$this->getFileInfo();
return $this;
}
private function getFileInfo() {
$result = $this->getDb()->query("SELECT directory, filename FROM files WHERE id = {$this->getId()};");
$row = $this->getDb()->fetch($result);
$this->_directory = $row['directory'];
$this->_filename = $row['filename'];
}
public function getDirectory() { return $this->_directory; }
public function getFileName() { return $this->_filename; }
public function getId() { return $this->_id; }
}
然后是下载课程。下载类接收$ user和$ file的实例。设置属性file_id和user_id后,使用这些实例调用下载类
class Download {
private $_path;
/**
* @var File
*/
private $_file;
/**
* @var User
*/
private $_user;
/**
* @var Download
*/
private $_size, $_info, $_ext, $_handle;
private static $_inst = null;
/**
*
* @param User $user
* @param File $file
* @return Download
*/
public static function init(User $user, File $file) {
if (self::$_inst == null) {
self::$_inst = new self();
self::$_inst->_file = $file;
self::$_inst->_user = $user;
self::$_inst->setPath();
}
return self::$_inst;
}
/**
* @return File
*/
public function getFile() { return $this->_file; }
/**
* @return User
*/
public function getUser() { return $this->_user; }
private function setPath() {
$this->_path = $this->getFile()->getDirectory() . DIRECTORY_SEPARATOR . $this->getFile()->getFileName();
}
public function getPath() { return __DIR__.DIRECTORY_SEPARATOR.$this->_path; }
private function setFileInfo() {
$this->_handle = fopen($this->getPath(), 'r');
$this->_size = filesize($this->getPath());
$this->_info = pathinfo($this->getPath());
$this->_ext = strtolower($this->_info['extension']);
}
private function setHeaders() {
switch ($this->_ext) {
case '.docx':
header("Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
case '.doc':
header("Content-type: application/msword");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
case '.txt':
header("Content-Type:text/plain");
header("Content-Disposition: attachment; filename=\"".$this->_info['basename']."\"");
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$this->_info['basename']."\"");
}
header("Content-length: $this->_size");
header("Cache-control: private");
}
public function forceDownload() {
$this->setFileInfo();
$this->setHeaders();
while(!feof($this->_handle)) {
fread($this->_handle, 2048);
}
fclose($this->_handle);
return true;
}
}
然后你需要像
这样的东西$user = new User();
$file = new File;
$user->setId(8);
$file->setId(3);
Download::init($user, $file)->forceDownload();
您也不能回显文件的基本名称,但也不能回复其他名称,因此您不会透露其名称