Play Framework Image BLOB File for Test Object Yam

2020-07-13 03:58发布

问题:

How do you set up a Test Blob Image using the yaml structure?

Also, what is the database structure for a BLOB file? (MySQL)

回答1:

I have experienced the same kind of problem a while ago on a project. However as I could not find a way to solve this with the fixtures (as the database stores the blob object as a string as Pere explained above), I created a workaround to at least solve this problem in a test-case-scenario. I created the following file /app/job/Bootstrap.java:

import play.test.*;
import play.jobs.*;
import play.db.DB;
import models.*;

import java.util.List;

@OnApplicationStart
public class Bootstrap extends Job {
     public void doJob() {
        // Load default data if the database is empty
        if(Item.count() == 0) {
            Fixtures.loadModels("my_fixtures.yml");
            List<Item> allItems = Item.findAll();
            for (Item a: allItems){
                DB.execute("UPDATE `Item` SET image='item_" + a.name.toLowerCase() + ".png|image/png' WHERE id=" + a.getId());
            }
        }
    }
}

The first thing I do is filling the database with initial data if there are no 'Item' already stored in the database.
The second thing is iterating over all the 'Item' which play! just stored in the database, which are read from the "my_fixtures.yml" file. Here for each item the string field will get updated as shown in the example above.

I know this is not exactly the answer to question in the OP, but it gives some kind idea to work around this issue..

EDIT: In the example given above I assume that the pictures are uploaded manually to your attachment folder as given in your application.conf, and that each image name is like: "item_<item_name_in_lowercase>" with a ".png" extension



回答2:

Well, play is quite weird on that point.

The blob is not saved into the database but in a upload folder defined in your application.conf. It is the path toward the file that is saved in the database.

I cannot check it right now, but I seem to recall they are saved as textuel representations (VARCHAR, TEXT)



回答3:

The blob is saved in the file system, by default under "data/attachments" if I recall correctly, but you can change that in the configuration (application.conf)

In the database, it's stored as a String (varchar in most DB) with two components: the name and the mime type. It looks like:

12345asbcdefghi12345abcdfed|image/jpeg

The first part is the name of the file. When you upload a file Play generates a unique UUID as name to avoid collision. Yes, this means you are loosing the original name. (note: now I'm having doubts on the name part, I would swear it is lost, but I may be wrong!)

The second part (after the |) is the myme type. Play uses a magic-myme library to automatically detect it.

You can see the code here.



回答4:

Here is a modified version of Unji's answer that loads the images from a folder in conf, please note that I have removed all the import statements:

/**
 * A job executed when the application starts.
 */
@OnApplicationStart
public class Bootstrap extends Job {

  /**
   * Loads the initial data if there are no
   * WebAdministrators at the database.
   * <p>
   *   It loads images on the post with the following criteria:
   *   <ol>
   *     <li>file loaction: /conf/initialMedia/</li>
   *     <li>file name: {post.title.toCamelCase()}-{i}.jpg</li>
   *   </ol>
   *   Where i must start in 0.
   * </p>
   */
  @Override
  public void doJob() {
    // Check if the database is empty
    if(WebAdministrator.count() == 0) {
      Logger.info("Loading Initial Data.");
      Fixtures.loadModels("initial-data.yml");
      List<Post> posts = Post.findAll();
      for (Post post: posts) {
        Logger.info("Looking for files for post: [" + post.title + "]");
        for (int i=0; true; i++) {
          VirtualFile vf = VirtualFile.fromRelativePath("/conf/initialMedia/"
              + JavaExtensions.camelCase(post.title) + "-" + i + ".jpg");
          File imageFile = vf.getRealFile();

          if (imageFile.exists()) {
            try {
              Blob blobImage = new Blob();
              blobImage.set(new FileInputStream(imageFile), MimeTypes.getContentType(imageFile.getName()));
              MediaItem mediaItem = new Image(blobImage);
              mediaItem.save();
              post.mediaItems.add(mediaItem);
              post.save();
              Logger.info("File: [%s] Loaded", imageFile.getAbsolutePath());
            } catch (FileNotFoundException e) {
              // this should never happen.
            }
          } else {
            Logger.info("Media Loaded for post [%s]: %d files.", post.title, i);
            break;
          }
        }
      }
    }
  }
}