Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 message. 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
like image 788
Hammerite Avatar asked Feb 04 '11 18:02

Hammerite


1 Answers

Are you sure there is no problem with your internet connection? Have you tried it from a different connection or even ISP?

like image 68
SkaveRat Avatar answered Nov 13 '22 15:11

SkaveRat