【问题标题】:JPEG files uploaded to a PHP script arrive corrupt - but not all the time上传到 PHP 脚本的 JPEG 文件损坏 - 但并非总是如此
【发布时间】:2011-02-04 18:54:04
【问题描述】:

我有一个 PHP 脚本,我将 JPEG 图像上传到该脚本(通过 HTML 表单)。你可以看到代码here,但我会尝试在这篇文章中展示相关部分。表单声明如下:

<form action="adm_addphoto.php" method="POST" enctype="multipart/form-data" name="myform">

MAX_FILE_SIZE 表单域设置为 5MB:

<input type="hidden" name="MAX_FILE_SIZE" value=5242880>

我要上传的图片大小约为 3MB。

上传后,我将图像文件转换为 GD jpeg:

$filename = $_FILES['file']['tmp_name'];
$myImage = imagecreatefromjpeg($filename);

有时上传工作正常,有时imagecreatefromjpeg 会发出有关 JPEG 已损坏的警告。例如(为便于阅读添加了换行符):

Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]:
         gd-jpeg, libjpeg: recoverable error: Corrupt JPEG data:
         47 extraneous bytes before marker 0xd9 in
         /path/adm_addphoto.php on line 97

Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]:
         '/tmp/phpwlSS9x' is not a valid JPEG file in
         /path/adm_addphoto.php on line 97

问题是,这不会可靠地发生。也就是说,如果我连续多次尝试相同的图像,有时会成功上传,有时会出现错误。在导致错误的尝试中,错误消息的细节也会有所不同。 (对于产生上述消息的特定照片,“无关字节”的数量有时是 47,有时是 20,有时是 68。)

什么可能导致文件在某些​​尝试中损坏,但在其他尝试中却没有?

PS。我知道有一个 ini 设置告诉 GD 努力处理损坏的 JPEG。但这不是重点,我想知道为什么上传的结果不一致。

PPS。以下是一些可能相关的 PHP ini 设置的值:

memory_limit .......... 128M
post_max_size ......... 8M
file_uploads .......... On
max_file_uploads ...... 20
upload_max_filesize ... 128M
upload_tmp_dir ........ no value

更新:我添加了代码以在文件上传后回显文件的大小和 MD5 校验和。大小始终是正确的文件大小(我的本地文件副本的大小)。但是,MD5 在尝试之间会有所不同。当 MD5 正确(与我的本地副本的 MD5 匹配)时,没有错误消息。当出现错误消息时,MD5 总是与预期不同。此外,这只是一种感知差异,但昨晚发生的错误似乎比今天早上更频繁——今天早上只有少数转移导致了错误。

这里有一些“糟糕”的上传(奇怪的是,有几个上传的 MD5 校验和与预期不同,但没有产生错误):

                   Correct MD5: f7b9587f39c7332e62a08adf34cefbd0
-----------------------------------------------------------------
           38 extraneous bytes: 2a28c46079071d9d2e2fd49865b35d59
                                ce1c69f798953b201dcc35f85f3b29b4
                                b013a0428a71adff674a46e92372d46b
           71 extraneous bytes: a271928f3559b6deaa19804704b5bcb3
           92 extraneous bytes: cab2a10ad8535addaca3b19bcb607a30
 premature end of data segment: 4514d39db1d94ab691d6da26c0832cdb
                  No error (!): 83b2e3624ddcfdeb3efc10be81631916
                                07d0a97b21d423fdeb4c6f88d76f8cd3

更新:回应 Andre 和 Pekka:以下是同一张图片的两个版本的链接。 This one 是图像的原始副本,存储在我的机器上;我以通常将文件上传到我的虚拟主机的方式上传它,即我使用了 FTP 客户端。 This one 是同一张图片,使用我的脚本上传(但添加了一行以使用move_uploaded_file() 将其移动到该位置)。该上传的错误消息是“损坏的 JPEG 数据:30 个无关字节......”。您会注意到图像的底部看起来不正确。对于图片尺寸过大,我深表歉意,但我只能举例说明给我带来问题的图片类型。

  • 我应该明确指出,这与我用于上述 MD5 校验和的图像不同。我没想过要使用同一张图片。

更新:使用上面链接的两个图像,我发现了两个文件之间的差异。有两个 32 字节的序列在一个图像中与另一个不同。这些文件在其他方面是相同的。

n.b. the first character is numbered as character 1, not character 0

n.b. 2116624 and 2493456 are both 16 modulo 32.
     The difference between them is 368 * 1024.

character 2116624 through line 2116655 (32 characters):

    original image:

    3c bc 20 19 eb 93 cd 34 db 93 68 7c 8d 5e 37 d4
    d3 84 91 70 7e 7c 82 3e e9 e8 3d eb 2e ff 00 ce

    bad image:

    89 c9 54 a6 e5 3d f4 fc 8e 7f 68 d5 47 14 41 f6
    55 11 7d a6 55 24 a8 e0 f7 a8 a4 43 06 18 c2 c1

character 2493456 through character 2493487 (32 characters):

    original image:

    3d a4 61 37 19 75 63 2e 51 62 ca 07 e0 9e 49 35
    5d 65 8d 22 01 7f 5e b4 a7 19 3a 7a ef 72 1c e3

    bad image:

    4f 99 26 39 6a db d9 cd 3e 5b ec 63 46 3c b4 ef
    2d b6 30 35 0f 12 a1 b6 9a 11 68 1a 69 07 0c 49

【问题讨论】:

  • 您是否从日志条目中获得了这些错误消息?谁在上传?
  • 我正在上传。这些错误是输出到浏览器的,因为我正在尝试调试问题,所以我启用了错误报告。
  • 只是为了确定,您是否只有一个网络服务器,所以只有一个 php/gd 配置?
  • 查看本地 JPEG 文件的前几个字节和上传的文件可能会有所帮助。 JPEG-magic-number 之前似乎出现了一些意外字节。
  • 是的,你能举一些实际的例子吗?这可能是格式问题

标签: php file-upload


【解决方案1】:

您确定您的互联网连接没有问题吗?您是否从其他连接甚至 ISP 尝试过?

【讨论】:

  • 当我有机会在我的工作机器上试用时,我会尽快回复您。
  • 好吧,我尝试在工作时从我的机器上传 4 张图片,每张 10 次,但我根本没有看到任何错误 - 所以我不得不得出结论,这很可能只是一个问题我的互联网连接。无法更准确地诊断问题所在,也无法对此采取任何措施,这是一种耻辱。我想我只需要上传我的工作照片。
【解决方案2】:

这有点牵强,但我能想到的一个可能问题是您正在处理临时文件,尝试使用 move_uploaded_file 将文件移动到您指定的位置,看看是否有区别?

【讨论】:

  • 我现在尝试添加使用 move_uploaded_file() 来移动文件的代码,然后再尝试使用它。它似乎对错误消息或它们发生的频率没有任何影响。
【解决方案3】:

此时不要尝试转换,而是转储临时文件信息并比较文件大小等。

由于这种随机性,它可能是某种形式的传输问题。您可能可以通过尝试将大小合适的 zip 文件(例如)从您正在运行的计算机移动到本地网络上的其他东西(多次)然后查看 zip 文件是否通过 crc 检查或已损坏。

另外:您是否正在运行嗅探 http 流量的防火墙设备? (例如解开)

【讨论】:

  • 我在脚本中添加了一条与临时文件大小相呼应的行,并尝试上传文件几次。回显的文件大小始终相同:2803547,这是存储在我的机器上的文件副本的大小。无论错误消息是否出现,无论错误的具体情况如何,此文件大小都是相同的。
  • 我正在运行 Windows Vista SP2。 Windows 防火墙已启用。 (我尝试使用 Opera,它在 Windows 防火墙的配置中作为例外启用,并且看到了相同的行为。)我有 Avast!已安装防病毒软件(免费版)。我没有安装商业防火墙。我通过宽带路由器从家里连接到互联网。另外:请参阅我对问题的更新,回复:MD5 校验和。
猜你喜欢
  • 1970-01-01
  • 2017-05-23
  • 2018-10-20
  • 2013-10-20
  • 1970-01-01
  • 2018-12-07
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多