0
votes

I'm using JSR-286 + Struts 2.2.0 + PortletPlugin 2.2.0

I can't set name for file which user wants to download. User can get file, but it's name is corrupted. Instead of "myImage.png" user gets "241883e9" or "241563a2". If users renames downloaded file and opens it he can see that the file is not corrupted. Please, see my code:

file-listing.jsp:

<li onclick="goToAction('<s:url action="downloadattachement" portletUrlType="resource" />', {'attachementId':<s:property value="id" />}, 'POST')"><s:property value="name"/></li>

function "goToAction" dynamically generates from and submits it (I've tried both: POST and GET, it doesn't help.):

<form action="/wps/myportal/!VERY_LONG_PORTAL_URL_GOES_HERE/" method="POST" id="actionUrlTemporaryForm1295987206509"> <input type="hidden" name="attachementId" value="2" /> </form>

my struts xml config file:

<!-- Download attached file by attachementId -->
    <action name="downloadattachement" class="ru.portal.DownloadAttachementAction">
        <result name="success" type="stream">
            <param name="allowCaching">false</param>
            <param name="contentType">${contentType}</param>
            <param name="inputName">attachementContents</param>
            <param name="contentDisposition">>attachment;filename="${fileName}"</param>
            <param name="bufferSize">1024</param>
        </result>
    </action>

And an action code:

@Override
    protected String bareExecute() throws Exception {
        String result = Action.SUCCESS;     
        Attachement attachement = EJBUtil.lookup(IAttachementManager.class).get(attachementId);
        LOG.info("Trying to download Attachement[{}]", attachement);
        File attachementFile = new File(attachement.getPath());     
        if(attachementFile.exists()){
            attachementContents = new FileInputStream(attachementFile);
        }else{
            LOG.error("There is no attachement[{}] file here[{}]",attachementId, attachement.getPath());
        }


        return result;
    }

    public String getContentType(){
        return attachement.getMimeType();
    }

    public String getFileName(){
        LOG.trace("#getFileName {}", attachement.getName());
        return attachement.getName();
    }

    public Integer getAttachementId() {
        return attachementId;
    }

    public void setAttachementId(Integer attachementId) {
        this.attachementId = attachementId;
    }

    public Attachement getAttachement() {
        return attachement;
    }

    public InputStream getAttachementContents() {
        return attachementContents;
    }

    @Override
    public String getCurrentActionName() {      
        return "downloadattachement";
    }

I've never seen this LOG line in my log file: LOG.trace("#getFileName {}", attachement.getName());

But I see

[25.01.11 23:26:46:582 MSK] 00000052 srt W com.ibm.ws.webcontainer.srt.SRTServletResponse setHeader WARNING: Cannot set header. Resp onse already committed.

Seems like I can't set headers for response... :(

What do I do wrong? Please help.

UPD: I've found partial solution: I've added this code to my action:

PortletActionContext.getResponse().setProperty("content-Disposition", "attachment;filename=\""+attachement.getName()+"\"");                     
PortletActionContext.getResponse().setProperty("content-Type", attachement.getMimeType());

The problem is in file name now: if it contains non ascii char file name is corrupted. File names like: "my file.doc", "02.png" work fine.

1

1 Answers

1
votes

The problem was in result type="stream" and also in filename attribute value of "Content-disposition" header. For FF I've used ISO-8859-1, for IE6-8 I've used url-encoding. I've used user-agent header to determine browser. My solution has only one issue, but for me it's acceptabe: IE8 replaces whitespaces in file names with underscores. For example "my fav image.png" will be "my_fav_image.png" is IE8. FF does undestand default encoding for HTTP and doesn't try to corrupt filename attribute value. You can find additional info here, on StackOverflow.