用不同的浏览器在playframework中上传文件 [英] File upload in playframework with different browsers

查看:203
本文介绍了用不同的浏览器在playframework中上传文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用playframework来建立一个网站。我还使用了一个名为 xheditor 的丰富编辑器。



Xheditor支持ajax-fileuploading,它需要服务器端有一个动作,接受包含上传文件的filedata参数。

一个上传操作:

pre code $ public class Application extends Controller {
public static void upload(File filedata){
// filedata不应该为空
renderText({'err':'','msg':{'ur':'/ uploaded / xxx.zip'}});






它在IE6中正常工作,filedata不为null并包含正确的数据。但是,如果我使用chrome或firefox,那么filedata就是 null !!

我使用萤火虫监视萤火虫提交的内容,提交这样的头文件:

  content-disposition 
attachment; NAME = FILEDATA;文件名=051111twdns.zip

我认为play并没有正确处理这种情况,所以参数 filedata为null。

为了使用chrome和firefox,我修改了这个动作:

<$ p $公共类应用程序扩展控制器{
public static void upload(File filedata){
if(filedata!= null){
// ok,它是IE6
renderText({'err':'','msg':{'ur':'/ uploaded / xxx.zip'}});
} else {
//它是chrome或firefox,数据在request.body
文件targetFile = new File(upload / test.zip);
IOUtils.copy(request.body,new FileOutputStream(targetFile));





这是在IE6中工作的, chrome和firefox,只有在上传文件非常小的情况下。例如。小于4K。如果它稍大,例如12K,IOUtils.copy方法会报告Read Error!,即使下面的代码也会报错:

pre $ code> request.body.available()
request.body.read()
request.body.read(bytes)


解决方案

你应该看看play.data.parsing.ApacheMultipartParser类,它从HTTP请求管理文件附件提取。

getFieldName获得字段搜索头content-disposition和form-data的名字。在你的情况下,它不存在。

  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);
//参数解析器可以处理空输入
Map params = parser.parse(cd,';');
fieldName =(String)params.get(name);
if(fieldName!= null){
fieldName = fieldName.trim();
}
}
return fieldName;





在getFileName中,它搜索标题content-disposition然后

  private String getFileName(Map / * String,String * /头文件){
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);
//参数解析器可以处理空输入
Map params = parser.parse(cd,';');
if(params.containsKey(filename)){
fileName =(String)params.get(filename);
if(fileName!= null){
fileName = fileName.trim();
// IE7返回完整路径名(#300920)
if(fileName.indexOf('\\\')!= -1){
fileName = fileName.substring(fileName.lastIndexOf ('\\')+ 1);
}

} else {
//即使没有值,参数是
//所以我们返回一个空文件名而不是文件
//名称。
fileName =;
}
}
}
}
return fileName;





$ b

显然,在你的情况下,这段代码将找到文件名,但不是字段名称,所以也许这就是为什么你的filedata字段设置为null在你的控制器。



为什么它与IE6? (因为它从来没有真正的标准,做一些别人不再做的:))

有关信息,在Crud模块,fileField。 html声明文件上传如下:

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

问候


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)

解决方案

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

这篇关于用不同的浏览器在playframework中上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆