sachax sachax - 5 months ago 19
PHP Question

How to check if an image file ftp is complete (via Nikon wireless image upload) with a php cron

I have created a small app for a photographer that shoots live pictures during music events.


  1. The images are sent from the Nikon camera to my ftp server.

  2. The app checks (cron) wether in the specified folder there are new images

  3. Then copies them to the "develop" folder, processes them with ImageMagick (resizing, filtering and watermarking)

  4. Then moves them to the "send" folder and attaches them to an email that is sent to specified recipients.



The problem: i'd like to be able to check if the images are completely uploaded before processing them. The cron runs every 5 minutes and the photographer shoots continuously during a concert.

I have been checking here for similar questions but I didn't really find a solution. So, in case is a duplicated question, I apologise for that.

Thanks, s@ch@x

UPDATE #1 - Here's the test I have made with Mark Setchell's suggestion:

`exec("convert -regard-warnings -size 1280x44.879451 xc:none -gravity center -pointsize 24 -font 'Times-Bold' -stroke black -strokewidth 1 -annotate 0 '©M.Setchell' -background none -shadow 100x3+0+0 +repage -stroke none -fill white -annotate 0 '©M.Setchell' roll/SUBSONICA.JPG +swap -gravity south -geometry +0-3 -composite send/SUBSONICA.JPG && rm roll/SUBSONICA.JPG");`


and

`exec("convert -size 1280x44.879451 xc:none -gravity center -pointsize 24 -font 'Times-Bold' -stroke black -strokewidth 1 -annotate 0 '©M.Setchell' -background none -shadow 100x3+0+0 +repage -stroke none -fill white -annotate 0 '©M.Setchell' roll/SUBSONICA.JPG -regard-warnings +swap -gravity south -geometry +0-3 -composite send/SUBSONICA.JPG && rm roll/SUBSONICA.JPG");`


Following vars come from php:

-size 1280x44.879451
(
$imageSize = getimagesize($developDir . $developFile);
)

-annotate 0 '©M.Setchell'
(
$watermark
)

roll/SUBSONICA.JPG
(the input file:
$developDir . $developFile
in the
foreach
statement)

send/SUBSONICA.JPG
(output file:
$sendDir . $developFile
in the
foreach
statement)

By testing, while uploading images manually via ftp, I got the email expected with 8 attachments, of which 4 where still partial images.

UPDATE #2 - I added in the
exec
function an array for the output and a var for the return status of the executed command - as in @Mark Setchell's update below.

Then, with a simple
if ... else
statement, I could easily analyse the result:


  • if (return status == 1) the image file is not a valid and completed one, so we remove the image from the processed folder (the "send" folder in my app)

  • else (return status == 0) file is a valid & a complete image file: we remove the file from the ftp folder where the photographer sends the images directly from the Nikon camera (the "roll" folder in my app).



So, the correct and complete
exec
string, based on @Mark Setchell's answer, is:

`convert -regard-warnings -size 1024x40 xc:none -gravity center -pointsize 20 -font 'Times-Bold' -stroke black -strokewidth 1 -annotate 0 '©2016 Mark Setchell' -background none -shadow 100x3+0+0 +repage -stroke none -fill white -annotate 0 '©2016 Mark Setchell' roll/SUBSONICA_small.jpg +swap -gravity south -geometry +0-3 -composite send/SUBSONICA_small.jpg`


Here's the code snippet that worked perfectly:

exec("convert $im_cmd", $convert_output, $returned_var);
if ($returned_var) {
unlink($send_dir . "/" . $developFile);

} else {
unlink($develop_dir . "/" . $developFile);
}


This solution works perfectly and after 10 tests it proved super-reliable: instead of checking the files via php, as the initial question asked, @Mark Setchell's approach - the use of the
-regard-warnings
option of the Imagemagick convert program link – solved the problem.

Answer

Updated Answer

Ok, we are close now! If you want to use PHP rather than the command-line, you need to get the return value from exec() do something dependent on that value. So, if you check here, you can see how to get the return value:

exec("convert -regard-warnings inputfile ... resize ... filter ... output/outputfile",array &$output, int &$return_var);

Then, if the $return_var is zero, you need to remove the input file because the command worked, and if it is non-zero, you need to remove the output file because it didn't.

Original Answer

You could let ImageMagick tell you if the file is incomplete. So, rather than copying the files blindly and "en masse" from the FTP directory, use Imagemagick convert to process them from there to the processed directory and only remove the ones that get processed successfully, leaving any others to be processed on the next cron invocation on the basis that they were incomplete. So, something like this:

cd FTPDirectory
for f in *.jpg; do
    convert -regard-warnings ... resize ... sharpen ... "%f" processed/"%f"
    # If successful, delete source file
    if [ $? -eq 0 ]; then
        rm "%f"
    fi
done

The -regard-warnings flag causes warnings to be treated as errors. So, if I don't use it, I get no error status when processing an incomplete file:

convert incomplete.jpg  processed.jpg
convert: Premature end of JPEG file `incomplete.jpg' @ warning/jpeg.c/JPEGWarningHandler/352.
convert: Corrupt JPEG data: premature end of data segment `incomplete.jpg' @ warning/jpeg.c/JPEGWarningHandler/352.

echo $?
0

Whereas if I do use it, I get a catchable error:

convert -regard-warnings incomplete.jpg  processed.jpg
convert: Premature end of JPEG file `incomplete.jpg' @ warning/jpeg.c/JPEGWarningHandler/352.
convert: Corrupt JPEG data: premature end of data segment `incomplete.jpg' @ warning/jpeg.c/JPEGWarningHandler/352.

echo $?
1
Comments