JPEG files uploaded to a PHP script arrive corrupt - but not all the time
I have a PHP script to which I upload JPEG images (through an HTML form). You can see the code here, but I will attempt to present the relevant parts in this post. The form is declared like so:
<form action="adm_addphoto.php" method="POST" enctype="multipart/form-data" name="myform">
The MAX_FILE_SIZE
form field is set to 5MB:
<input type="hidden" name="MAX_FILE_SIZE" value=5242880>
The images I want to upload are about 3MB in size.
Once it's uploaded, I turn the image file into a GD jpeg:
$filename = $_FILES['file']['tmp_name'];
$myImage = imagecreatefromjpeg($filename);
Sometimes the upload works fine, and sometimes imagecreatefromjpeg
emits warnings about the JPEG being corrupt. For example (line breaks added for readability):
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
The thing is, this doesn't happen reliably. That is, if I try the same image several times in a row, sometimes it will upload successfully and sometimes there will be errors. And within the attempts that result in errors, the specifics of the error message will vary too. (With the particular photo that produced the above messages, the number of "extraneous bytes" is sometimes 47, sometimes 20, occasionally 68.)
What might be causing the files to arrive corrupt on some attempts but not others?
PS. I know that there is an ini setting that tells GD to try hard to work with corrupt JPEGs. But that's not the point, I want to know why the result of the upload is inconsistent.
PPS. Here are the values of some possibly-relevant PHP ini settings:
memory_limit .......... 128M
post_max_size ......... 8M
file_uploads .......... On
max_file_uploads ...... 20
upload_max_filesize ... 128M
upload_tmp_dir ........ no value
UPDATE: I added code to echo out the size and MD5 checksum of the file once it was uploaded. The size is always the correct filesize (the size of my local copy of the file). The MD5, however, varies between attempts. When the MD5 is correct (matches the MD5 of my local copy), there is no error me开发者_如何转开发ssage. When there is an error message, the MD5 is always different from expected. Also, this is just a perceived difference, but errors seemed to be occurring more frequently last night than this morning - only a minority of transfers this morning resulted in an error.
Here are some "bad" uploads (curiously, there were a couple of uploads that gave an MD5 checksum different to that expected but did not produce errors):
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
UPDATE: In response to Andre and Pekka: Here are links to two versions of the same picture. This one is the original copy of the image, as stored on my machine; I uploaded it the way I usually upload files to my webhosting, i.e. I used an FTP client. This one is the same image, uploaded using my script (but with a line added to move it to that location using move_uploaded_file()
). The error message on that upload was "Corrupt JPEG data: 30 extraneous bytes...". You will notice that the bottom part of the image appears incorrect. I apologise for the large size of the images, but I can only use examples of the type of images that are giving me problems.
- I should make it clear that this is a different image to the one that I used for the above MD5 checksums. I didn't think to use the same image.
UPDATE: Using the two images I linked above, I found the differences between the two files. There are two sequences of 32 bytes that are different in one image from the other. The files are otherwise identical.
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
Are you sure there is no problem with your internet connection? Have you tried it from a different connection or even ISP?
Its a stretch, but one possible issue I can think of is that you're working on the temporary file, try using move_uploaded_file to move the file to somewhere you've specified, and see if that makes a difference?
Rather than attempt a conversion at this point, dump the temp file info and compare the file size etc.
Because of the random nature of this, it is probably some form of transmission problem. You can probably rule out your own hardware by trying to move a decent size zip file (for example) from the computer you are running to something else on the local network (multiple times) and then seeing if the zip file passes the crc check or becomes corrupted.
Also: are you running a firewall appliance which sniffs http traffic? (e.g. untangle)
精彩评论