Question

I'm using playframework to build a web site. And I also use a rich editor named xheditor.

Xheditor support ajax-fileuploading, it needs the server side has a action which accepts "filedata" parameter which contains the upload file.

So I wrote a upload action:

public class Application extends Controller {
    public static void upload(File filedata) { 
        // the filedata should not be null
        renderText("{'err':'', 'msg':{'ur':'/uploaded/xxx.zip'}}"); 
    } 
}

It works fine in IE6, the filedata is not null and contains the correct data. But, if I use chrome or firefox, the filedata is null!!

I use firebug to monitor what the firebug submit, and found it submit such a header:

content-disposition
attachment; name="filedata"; filename="051111twdns.zip"

I think play has not handle this case correctly, so the parameter "filedata" is null.

In order to work with chrome and firefox, I modified that action:

public class Application extends Controller {
    public static void upload(File filedata) { 
        if(filedata!=null) {
            // ok, it's IE6
            renderText("{'err':'', 'msg':{'ur':'/uploaded/xxx.zip'}}"); 
        } else {
            // it's chrome or firefox, the data is in request.body
            File targetFile = new File("upload/test.zip");
            IOUtils.copy(request.body, new FileOutputStream(targetFile));
        }
    } 
}

This is worked in IE6, chrome and firefox now, BUT, only if the upload file is very small. E.g. less than 4K. If it's a little larger, e.g. 12K, the method "IOUtils.copy" will report "Read Error!", even the following code will report such error:

request.body.available()
request.body.read()
request.body.read(bytes)
Was it helpful?

Solution

You should take a look at play.data.parsing.ApacheMultipartParser class which manages the file attachment extraction from HTTP request.

The getFieldName gets the name of the field searching header "content-disposition" and "form-data". In your case, it's not present.

private String getFieldName(Map /* String, String */ headers) {
    String fieldName = null;
    String cd = getHeader(headers, CONTENT_DISPOSITION);
    if (cd != null && cd.toLowerCase().startsWith(FORM_DATA)) {

        ParameterParser parser = new ParameterParser();
        parser.setLowerCaseNames(true);
        // Parameter parser can handle null input
        Map params = parser.parse(cd, ';');
        fieldName = (String) params.get("name");
        if (fieldName != null) {
            fieldName = fieldName.trim();
        }
    }
    return fieldName;
}

in the getFileName, it searches the header "content-disposition" and then "form-data" or "attachment" to get the file name.

private String getFileName(Map /* String, String */ headers) {
    String fileName = null;
    String cd = getHeader(headers, CONTENT_DISPOSITION);
    if (cd != null) {
        String cdl = cd.toLowerCase();
        if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) {
            ParameterParser parser = new ParameterParser();
            parser.setLowerCaseNames(true);
            // Parameter parser can handle null input
            Map params = parser.parse(cd, ';');
            if (params.containsKey("filename")) {
                fileName = (String) params.get("filename");
                if (fileName != null) {
                    fileName = fileName.trim();
                    // IE7 returning fullpath name (#300920)
                    if (fileName.indexOf('\\') != -1) {
                        fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
                    }

                } else {
                    // Even if there is no value, the parameter is present,
                    // so we return an empty file name rather than no file
                    // name.
                    fileName = "";
                }
            }
        }
    }
    return fileName;
}

So apparently, in your case, this code will find the filename but not the field name so maybe this is why you have your filedata field set to null in your controller.

Why does it work with IE6? (because it has never been really standard and does something the others don't do anymore ??? :) )

For information, in the Crud module, the fileField.html declares file upload as following:

<input id="${field.id}" class="${field.errorClass}" type="file" name="${field.name}" />

regards

OTHER TIPS

Try integrate your site with file uploader ,which have a lof of documentation/samples for diffrent languages www.uploadify.com/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top