【问题标题】:Decoding base64 file contents between PHP and C#在 PHP 和 C# 之间解码 base64 文件内容
【发布时间】:2012-04-22 00:24:48
【问题描述】:

我需要将 AES 加密的 base64 编码文件从 PHP 提供给 C# 客户端(Mono,在各种平台上)。我已经成功地让 AES 加密/解密工作正常,但是一旦我尝试 base64 编码/解码,我就会遇到麻烦。下面的两个示例都禁用了 AES,因此这不应该是一个因素。

我最简单的测试用例,一个 Hello World 字符串,工作正常:

PHP 服务输出-

// Save encoded data to file
$data = base64_encode("Hello encryption world!!");
$file = fopen($targetPath, 'w');
fwrite($file, $data);
fclose($file);

// Later on, serve the file
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".basename($product->PackageFilename($packageId)));
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($targetPath));
ob_clean();
flush();
$handle = fopen($targetPath, "r");
fpassthru($handle);
fclose($handle);

C#解码与使用-

StreamReader reader = new StreamReader(stream);
char[] buffer = DecodeBuffer;
string decoded = "";
int read = 0;
while (0 < (read = reader.Read(buffer, 0, DecodeBufferSize)))
{
    byte[] decodedBytes = Convert.FromBase64CharArray(buffer, 0, read);
    decoded += System.Text.Encoding.UTF8.GetString(decodedBytes);
}
Log(decoded); // Correctly logs "Hello encryption world!!"

然而,一旦我开始尝试对文件的内容做同样的事情,FormatException: Invalid character found 会被 Convert.FromBase64CharArray 抛出:

PHP 服务输出-

// Save encoded data to file
$data = base64_encode(file_get_contents($targetPath));
$file = fopen($targetPath, 'w');
fwrite($file, $data);
fclose($file);

// Later on, serve the file
// Same as above

C#解码与使用-

using (Stream file = File.Open(zipPath, FileMode.Create))
{
using (StreamReader reader = new StreamReader(stream))
{
    char[] buffer = DecodeBuffer;
    byte[] decodedBytes;
    int read = 0;
    while (0 < (read = reader.Read(buffer, 0, DecodeBufferSize)))
    {
        // Throws FormatException: Invalid character found
                    decodedBytes = Convert.FromBase64CharArray(buffer, 0, read);
        file.Write(decodedBytes, 0, decodedBytes.Length);
    }
}
}

是否应该对较大的数据进行某种额外的处理才能使 base64 有效?对大型二进制数据执行此操作是否不合适?如果是,您将如何防止传输不安全字符的潜在问题?

【问题讨论】:

  • 只是好奇。 fwrite 之后,php 是否可以打开该文件并正确解码?
  • 你需要弄清楚它不喜欢哪个角色。我猜这可能是编码问题。
  • @webbiedave 我想我没有检查过。当我再看它时,我会的。

标签: c# php stream base64


【解决方案1】:

您阅读的 Base64 文本代码不正确。

  • Base64 是文本,因此请考虑改用文本阅读器
  • Base64 可能包含新行/空格。 IE。习惯将整个 Base64 编码值拆分为 70-80 个字符长的字符串。

要验证文件中的数据是否正确,将整个文件读取为字符串 (StreamReader.ReadToEnd) 并转换为字节数组 (Convert.FromBase64String)。

如果文件包含有效的 Base64 数据并且您无法将其作为单个字符串读取,则应实现自己的 Base64 解码或手动读取正确数量的非空白字符(4 的倍数)并解码此类块。

【讨论】:

  • 啊,好吧,我将不得不尝试作为一个完整的字符串。我只是担心文件可能太大而无法在一个块中处理(此客户端代码有时会在内存可用性存在问题的移动设备上运行)。
【解决方案2】:

Base64 编码将 3 个八位字节转换为 4 个编码字符。因此,您提供用于解码的数据长度需要是 4 的倍数。

首先,确保DecodeBufferSize 是4 的倍数。接下来,由于StreamReader.Read 不能保证所有请求的字节都会被读取,您应该继续读入buffer,直到它被填满,或已到达流的末尾。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 1970-01-01
    • 2018-12-19
    • 2015-12-04
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多