πŸ“œ ⬆️ ⬇️

Static storage, processing and release

Beginners (and not so) developers often have questions about how to work correctly with user-generated content, and specifically with pictures. This topic has many aspects and more than one solution. Here, only one of the possible options will have its own advantages and disadvantages. We also assume that the static and code are stored on a single server, and the files are loaded one by one.

Tasks solved by the system:
- convenient file downloads;
- the possibility of asynchronous processing of images;
- easy work with previews;
- separation of configuration from execution.

Go
')


First, create a File table in the database with the following fields: id, name, size, width, height, is_deleted, is_ready, updated, created.

When loading a file, first of all, an entry will be created in the File table. Further, based on id, the path will be calculated by which it should be saved.

$number = sprintf('%08d', $id);
$uri = '/' .
substr($number, 0, 2) . '/' .
substr($number, 2, 2) . '/' .
substr($number, 4, 2) . '/' .
$number;


At the output we get something like this: / 00/47/31/00473161

upd1 Arkadiy_Kulev pointed out that it is better to limit the depth of directories to two levels.

upd2 Indeed, it is more correct to make a path in the reverse order for a better distribution of pictures into folders. Ie, we get the URL / 161/473/00473161. Thank you atd

What is it done for?


As can be seen from the example β€œ00/47/31/00473161”, the number of possible downloads of pictures, with this approach, is limited to a billion. Naturally it is easy to change at the implementation stage.

To implement the functionality described above, you need to create the Image_Manager class with the receive method. This class will be engaged in creating a record in the database and moving the file to the appropriate directory in the file system, as well as creating the missing directories.

...
if ($form->isValid()) {
// , Image_Manager
// $_FILE .
...
$im = new Image_Manager($options); //
// 'avatar' ,
$file_id = $im->receive('avatar'); //
$user->avatar_file_id = $file_id;
$user->save()
}


We saved the original image and gave it to the user id. But it still needs to be processed, and it is possible to create several preview sizes for display on the site. Then you can go in several ways, create images at once or use lazy load. The second method also has several options for development and is beyond the scope of this article (At the end of the article a list of links is given, where an example of a possible implementation of this method is given). We will go the first way. And it is for this purpose that the $ options array is passed to the image_manager constructor, and the β€œavatar” string is passed to the recive method.

In order to create thumbnails, you need a configuration file describing the types of images uploaded to the site and their parameters. For example (using the format Zend_Config_Ini):

...
[avatar] ; big, medium small
resize.big.OutputFileFormat = jpg
resize.big.keepFrame = true
resize.big.backgroundColor = 240.240.240
resize.big.width = 236
resize.big.height = 177
resize.medium.keepFrame = true
resize.medium.backgroundColor = 240.240.240
resize.medium.width = 144
resize.medium.height = 108
resize.small.keepFrame = true
resize.small.width = 72
resize.small.height = 54
resize.small.roundCorners = false

[user_album_photo]
...


It is this configuration file that is passed to the Image_Manager constructor. By calling the recive method, we specify a section of the configuration file and in fact we determine how this picture will be processed and how many previews will be created. To process images, it is desirable to have a separate library with which the Image_Manager interacts within itself.

To save the preview, use the same storage format of the source file β€œ00/47/31/00473161”, but at the end a special hash is added, calculated based on the parameters of this preview, as a result the path will be something like this ”/ 00/47/31 / 00473161X2280688952 .jpg "(again, this is just an example, you can do it differently). This hash helps determine the existence of a preview for images whose parameters have changed and, if there is no, generate an image upon request.

It remains to deal with the conclusion. The simplest option would be to write a special image helper, which will work like a url helper:

// url
$this->image($user->avatar_file_id, 'small', 'avatar')


The helper image refers to an object (possibly Image_Manager), which knows how to build a path to the current image, taking into account its parameters, section, and the name of the preview. If the pictures are on a separate host, then it substitutes it. In the absence of the necessary preview, the helper can generate it (controversially, with a large number of missing images, memory or timeout may end) or give way to a special stub for this type of file.

As a result, we got a convenient configuration file, file download in one line and a unified way to work with all site images, including user ones.

Related Links:
http://habrahabr.ru/blogs/nginx/77873/ - very valuable comments here
http://habrahabr.ru/blogs/nginx/94435/
http://ru.wikipedia.org/wiki/WebDAV - when moving static to a separate server (s)

Source: https://habr.com/ru/post/101654/


All Articles