1

I have try to insert user-defined css file into my template.

Model:

@Entity
public class MyModel extends Model {

    // Some code stuff...

    /** User-defined css file. */
    public Blob stylesheet;

}

Controller

public class MyController extends Controller {

    // Some code stuff...

    /**
     * Displays user-defined css file for specified instance of MyModel.
     */
    public static void displayStylesheet(Long id) {
        final MyModel myModel = MyModel.findById(id);
        notFoundIfNull(myModel);
        response.setContentTypeIfNotSet(myModel.stylesheet.type());
        if (myModel.stylesheet.exists()) {
            renderBinary(myModel.stylesheet.getFile());
        }
    }

    /**
     * Displays page, that contains user-defined css file
     * for specified instance of MyModel.
     */
    public static void index(Long id) {
        render(id);
    }

}

View

#{extends 'main.html' /}
#{set 'styles'}
  <link rel="stylesheet" href="@{MyController.displayStylesheet(id)}" />
#{/set}
<p>This page contains user-defined stylesheet.</p>

When I try to display stylesheet by GET request all working fine:

http://localhost:9000/mycontroller/displaystylesheet?id=1188

But FireBug or Google Chrome developer`s panel are not displays this style like sourced.

Updated:

I found the solution, but it is not so beautyfull. Code in the controller:

/**
 * Displays page, that contains user-defined css file
 * for specified instance of MyModel.
 */
public static void index(Long id) {
    final MyModel myModel = MyModel.findById(id);
    String styles = "";
    File stylesheet = myModel.stylesheet.getFile();
    try {
        FileInputStream stream = new FileInputStream(stylesheet);
        try {
          FileChannel fc = stream.getChannel();
          MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
          styles = Charset.defaultCharset().decode(bb).toString();
        }
        finally {
          stream.close();
        }
    }
    catch (IOException ioe){
        throw new RuntimeException(ioe);
    }
    render(id, styles);
}

It will put all styles into the one string styles. Then we can render it in the template:

<style type="text/css">
  ${styles}
</style>

May be someone can suggest more beautyfull solution?

1 Answer 1

3

The problem you are having, is that the content type is being returned as application/binary because you are using renderBinary, so the browser is ignoring it, because it is not of type "text/css".

When using renderBinary, the renderBinary code sets the contentType in a range of different ways depending on the parameters used. As you are using File, it determines the content type from the filename.

So, if you can guarantee that your filename is of type CSS, so when it performs MimeType.getContentType(filename); it will set the contentType accordingly.

Otherwise, you can change your code to something like this

public static void displayStylesheet(Integer id) {

    // ... read css data from file into a String
    String cssTextData = readCSSFromFile(); // <-- You can use the method you have used in your update here

    response.contentType = "text/css";
    renderText(cssTextData);
}
Sign up to request clarification or add additional context in comments.

3 Comments

I have #{get 'styles' /} in my main.html. Browser displays <link rel="stylesheet" href="/mycontroller/displaystylesheet?id=1188" /> but can not to load this stylesheet, but when I try to display stylesheet by GET request all working fine.
I have investigated further and can replicate your error, and have found a fix...(see edit).
Ok. I did a small refactor on your advice. Now it looks better. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.