如何在 PHP 中安全地返回文件数据

Posted

技术标签:

【中文标题】如何在 PHP 中安全地返回文件数据【英文标题】:How to return file data securely in PHP 【发布时间】:2015-04-30 19:03:25 【问题描述】:

底线问题:什么是正确的 php,以便我可以在基于 json 的响应对象中包含二进制数据文件?

我有一个正在与服务器通信的应用程序(ios,尽管这不重要)。我希望服务器在成功登录时返回一个文件。我确实希望可以通过浏览器或其他方式下载此文件。因此,文件目录受到保护,不会被公开浏览。

我在服务器上有一个文件结构,如下所示:

.../userFiles/
    myFile.zip
    yourFile.zip
    somebodyElsesFile.zip
    // all the other files, snip
.../server/
    login.php
    // other stuff, snip

userFiles/ 目录具有drwxrw---- 权限,并且与server/ 具有相同的所有者和组,所以我认为这部分是正确的。

我的服务器 PHP 代码有:

// A bunch of stuff, snip.
// by this point, user is already verified valid login.
$filePath = "../userFiles/$username.zip";
if (file_exists($filePath))

    // get the user's file
    $fileData = file_get_contents($filePath);
    if ($fileData)
    
        $response->addparameters(array('data' => $fileData));
        $response->addparameters(array('DEBUG-filePath' => $filePath));
    
    else
    
        $response->addparameters(array('msg' => "can't read data."));
        $response->addparameters(array('DEBUG-filePath' => $filePath));
        $response->setStatusCode(500);
    

else

    // deal with non-existent file, snip


$response->send();
exit();

当我从我的应用程序登录时,响应 json 如下所示:

myapp[13529:3615028] -[LoginViewController connection:didReceiveData:] ***** Login, but no data:
    
        "DEBUG-filePath" = "../userFiles/olie.zip";
        data = "<null>";
        token = [token redacted];
    

我做错了什么?更重要的是:什么是正确的 PHP,以便我可以在基于 json 的响应对象中包含二进制数据文件?

这并不重要(除了我使用的是应用程序,而不是浏览器来访问此 API),但我在 iOS 中运行,并且一旦这一切正常,我想要的获取文件数据的方式是:

NSData *zipFile = [json objectForKey: @"data"];
// unzip the file, deal with contents, snip.

其他信息:我的 $response 代码是 200,DEBUG-filePathdata 参数让我高度确定我在这个特定的代码路径上(而不是其他一些失败,其他地方。 )

我是 iOS 方面的专家,但对 PHP 很陌生。我设法上传并保存文件以正常工作,但在下次登录时无法返回。

任何提示将不胜感激。

谢谢!

【问题讨论】:

看起来像错字:$fileData = file_get_contents($farmFilePath); vs $fileData = file_get_contents($filePath); 不,这只是我的糟糕编辑。会修复。 (抱歉,我稍微修改了原文,试图删除所有对“农场”的引用,因为这不是问题的一部分。看起来我错过了 2,现在更正了。) 另外,我的响应对象是$response = new Response();;原始来源直接来自 bshaffer.github.io/oauth2-server-php-docs/cookbook 。我认为问题不存在,因为它的其他一切都可以完美运行(并且它作为 Oauth2 机制在“无处不在”中使用。)除非有一些奇怪的地方它不能正确处理二进制数据。我想我对事情的结局了解不多。 在传输过程中尝试base64编码内容。例如$data = base64_encode($data); 如果通信协议是json,我很确定二进制数据不会直接工作,因此建议使用base64编码传输。 【参考方案1】:

在传输过程中尝试对内容进行 base64 编码。例如$data = base64_encode($data);

如果通信协议是json,我很确定二进制数据不会直接工作,因此建议使用base64编码传输。

【讨论】:

是的,这给了我一大堆数据(而不是以前的 NSNull 对象。)我现在正在处理“字符 198 周围的未终止字符串”,但我要么在我的稍后拥有或提出新问题。谢谢! 为了节省人们几秒钟找到 other SO 答案,在 iOS 端获取该数据是:NSData *zipData = [[NSData alloc] initWithBase64EncodedString: zipData64 options: 0];(从 iOS 7 开始在 NSData 中新增: ) )

以上是关于如何在 PHP 中安全地返回文件数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP 安全地将 JSON 数据写入文件

sh 如何在特定文件夹中找到文件数?

如何计算每个目录中的文件数?

如何获取目录下的文件数(一行Python)

如何使用 gsutil 计算存储桶文件夹中的文件数

仅当文件数大于零时,如何在 MSBuild 中运行任务?