Reputation: 913
I have try to insert user-defined css file into my template.
@Entity
public class MyModel extends Model {
// Some code stuff...
/** User-defined css file. */
public Blob stylesheet;
}
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);
}
}
#{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.
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?
Upvotes: 1
Views: 998
Reputation: 54914
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);
}
Upvotes: 3