Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
1.5.10
-
Ubuntu 12.04, Sun JDK 1.6.0_38 64bit
Description
During the migration from Wicket 1.4 to 1.5.10 I found out that the ResourceStreamResource.respond() does not set the ContentType charset if the resource is of type StringResourceStream. Even though the stream holds the charset, it is not set, although quite a few other header parameters are (well this is understandable because not all ResourceStreams are StringResourceStreams. Also, it is difficult to call the resource.setTextEncoding, because the current flow in resourceStreamRequestHandler.respond does not allow easy overriding of any smaller piece of respond than the whole method. The practical issue was to download a CSV file by clicking a button. I managed to fix the issue by copy/paste/Overriding the ResourceStreamRequestHandler.respond, but IMHO this is not nice:
private void addCsvButton() {
Form<?> form = new Form<Void>("form") {
@Override
protected void onSubmit() {
final String fileName = getFileName("csv");
TableCsvResourceFactory factory = new TableCsvResourceFactory();
final IResourceStream resourceStream = factory.getResourceStream(tableModel.getObject());
ResourceStreamRequestHandler resourceStreamRequestHandler = new ResourceStreamRequestHandler(
resourceStream) {
final ContentDisposition contentDisposition = ContentDisposition.ATTACHMENT;
@Override
public void respond(IRequestCycle requestCycle) {
Attributes attributes = new Attributes(requestCycle.getRequest(), requestCycle.getResponse());
ResourceStreamResource resource = new ResourceStreamResource(resourceStream);
resource.setFileName(fileName);
if (contentDisposition != null)
else
{ resource.setContentDisposition(Strings.isEmpty(fileName) ? ContentDisposition.INLINE : ContentDisposition.ATTACHMENT); } final Duration cacheDuration = getCacheDuration();
if (cacheDuration != null)
+ resource.setTextEncoding("UTF-8");
resource.respond(attributes);
}
};
RequestCycle.get().scheduleRequestHandlerAfterCurrent(resourceStreamRequestHandler);
}
};
form.setVisible(displayCsv);
add(form);
}
There are a couple of problems with the current implementation of ResourceStreamRequestHandler:
1) I didn't figure out yet any other way how to call the
resource.setTextEncoding("UTF-8");
except by copy/pasting the whole ResourceStreamRequestHandler.respond() code to the Override. It would be nice, if there would be some cleaner hook to override some smaller part of this method, such as an empty default implementation of setTextEncoding() that would be always called but would not do anything for other types.
2) A second approach would be to create a StringResourceStreamRequestHandler extends ResourceStreamRequestHandler that would be otherwise the same, but would use IStringResource instead of IResource, and would also set the TextEncoding.
3) However, third, I didn't yet find any good way to get the encoding from the StringResourceStream itself, because the AbstractStringResourceStream has a protected getCharset(). This problem could be overcome by adding public version of getCharset() to StringResourceStream, or as I did, create a parallel subclass CharsetStringResourceStream that is a copy/paste from StringResourceStream but is non-final and has public getCharset(). After this you could dynamically set the text encoding in ResourceStreamRequestHandler.respond for example like this:
if (getResourceStream() instanceof CharsetStringResourceStream)
{ resource.setTextEncoding(((CharsetStringResourceStream)getResourceStream()).getCharsetName()); }Anyway, I think the usage of StringResourceStream with ResourceStreamRequestHandler should be improved somehow, at the moment I think it is a bit awkward to use.