lui
lui

Reputation: 440

Replace image on server and show previous image until the new one is fully uploaded

I'm uploading to a lightspeed server through "ncftpput" an image taken from a raspberry camera every minute.

I want to be able to show the updated image and I know how I can force the browser to use the latest version instead of the cached image.

So, everything works properly except that, if I refresh the image (like through shift-F5) during image upload, the browser reports image contains errors (or shows image partially).

Is there any way to ensure the image is fully loaded before serving the new one? I'm not sure if I should operate on ncftp or use PHP to ensure the swap happens only after complete loading.

Image is a progressive jpg but that doesn't help... Any suggestion? Thanks

Upvotes: 0

Views: 96

Answers (2)

lui
lui

Reputation: 440

I ended up with NOT using FTP because, as Viney mentioned, the webserver doesn't know if the upload is completed.

I'm using "curl" which has the advantage of being preinstalled on raspberry distro and a php upload page.

It seems that PHP will pass the new image only once fully uploaded and avoid creating the issue when image is still partially uploaded.

So, to recap:

raspberry (webcam), after having taken the image:

curl -F"somepostparam=abcd"  -F"operation=upload" -F"[email protected]" https://www.myserver.com/upload.php

PHP server code:

$uploadfile = '/home/domain/myserver.com/' . basename($_FILES['file']['name']);
move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);
$content = file_get_contents($uploadfile);

Upvotes: 2

Vinay
Vinay

Reputation: 7676

Problem is this: you open browser (at 07:00:10 AM) image.jpg gets rendered now say it's 07:01:00 you hit refresh in browser but the raspberry is already started uploading image.jpg say it would take 3 secs to complete the full upload but the server doesn't know about ftp and would read whatever bytes are there in image,jpg and flushes to your browser. Had it been a baseline JPG it would have shown a cropped(in height) image but since it's a progressive JPG it would be messed up.I am not aware of whether it's possible but try looking up if you FTP supports a locking file.

How to solve ?

The best way is to let you server know that the file it's accessing is in a write process.If your ftp supports advisory locks then you can use it so when server tries accessing you file ( via system call) kernel would instruct it that the file is currently locked so the server will wait until ftp releases that lock.

In vsftp there would be a option lock_upload_files in VSFTPD.CONF setting yest would enable this feature

If you are unable to work out above solution then you can use some trick like checking file last modified time if it's almost same as current time then you make php wait for some guessed time that you think is avg. upload time of your file.For this method you should use PHP to send it to browser instead of server. ie Just change the src of your image from '/path/to/image.jpg' to 'gen-image.php'. This script will read that image and would flush it to the browser

gen-image.php

$guessedUploadTime = 3;// guessed time that ncftpput takes to finish
$currTime = time();
$modTime = filemtime('image.jpg');

if( ($currTime - $modTime) < $guessedUploadTime)
{
    sleep($guessedUploadTime);
}

$file = '/path/to/image.jpg';
$type = 'image/jpeg';
header('Content-Type:'.$type);
readfile($file);

Note that the above solution is not ideal because if file has been just done uploading it won't be modified for another 57 seconds yet the browser request say at 07:02:04 has to wait unnecessarily for 3 seconds because mtime would be 07:02:03 and browser would get file only after 07:02:06. I would recommend you to search for some way(proly cmd based) to make server and ftp go hand in hand one should know the status of the other because that is the root cause of this problem.

Upvotes: 1

Related Questions