Play Framework: вопрос отображения изображения - PullRequest
4 голосов
/ 18 июня 2011

ref: http://www.lunatech -research.com / playframework-file-upload-blob

Меня беспокоит один момент в этом примере

  #{list items:models.User.findAll(), as:'user'}
  <img src="@{userPhoto(user.id)}">
  #{/list}

На данный момент я уже держу объект пользователя (включая блоб изображения).И все же метод userPhoto () делает еще один шаг в серверную часть, чтобы получить изображение user.photo

    public static void userPhoto(long id) {
       final User user = User.findById(id);
       notFoundIfNull(user);
       response.setContentTypeIfNotSet(user.photo.type());
       renderBinary(user.photo.get());
    }

Любой способ избежать этого ненужного вызова findById?

1 Ответ

5 голосов
/ 18 июня 2011

Вы на самом деле больше не удерживаете объект пользователя, потому что действие userPhoto вызывается в отдельном запросе, который отправляется, когда браузер пытается загрузить изображение с URL-адреса, созданного @{userPhoto(user.id)}.

Конечно, вы могли бы использовать кэш для хранения данных из каждого блоба с фотографиями каждого пользователя, что уменьшило бы вероятность того, что вам нужно было перейти в базу данных по запросу изображения. Однако в этом случае это больше проблем, чем стоит, поскольку вы просто просматриваете первичный ключ для пользовательского объекта, и это должно быть относительно недорого. Кроме того, BLOB-объекты не сериализуемы, поэтому вы должны извлекать каждый фрагмент информации отдельно.

Тем не менее, если бы вы попробовали, это могло бы выглядеть примерно так:

// The action that renders your list of images
public static void index() {
    List<User> users = User.findAll();

    for (User user : users) {
        cachePhoto(user.photo);
    }

    render(users);
}

// The action that returns the image data to display
public static void userPhoto(long id) {
    InputStream photoStream;
    String path = Cache.get("image_path_user_" + id);
    String type = Cache.get("image_type_user_" + id);

    // Was the data we needed in the cache?
    if (path == null || type == null) {
        // No, we'll have to go to the database anyway
        User user = User.findById(id);
        notFoundIfNull(user);
        cachePhoto(user.photo);
        photoStream = user.photo.get();
        type = user.photo.type();
    } else {
        // Yes, just generate the stream directly
        try {
            photoStream = new FileInputStream(new File(path));
        } catch (Exception ex) {
            throw new UnexpectedException(ex);
        }
    }

    response.setContentTypeIfNotSet(type);
    renderBinary(photoStream);
}

// Convenience method for caching the photo information
private static void cachePhoto(Blob photo) {
    if (photo == null) {
        return;
    }

    Cache.set("image_path_user_" + user.id,
            photo.getFile.getAbsolutePath());
    Cache.set("image_type_user_" + user.id,
            photo.getType());
}

Тогда вам все равно придется беспокоиться о правильном заполнении / аннулировании кэша в ваших действиях добавления, обновления и удаления. В противном случае ваш кэш будет загрязнен устаревшими данными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...