给出:
public ICommand AddBookCommand
{
get
{
return _addBookCommnad ?? (_addBookCommand = new CmandHandler<object>((par) => AddBookAction(par), _canExecute));
}
}
public void AddBookAction(object obj)
{
//This is where I want to add a new BookModel to the
IObservableCollection<IObservableCollection<BookModel>> at the location
given by the pressed button
}
是
byteString
然后此代码(未优化):
-----------------------------149742642616556
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
test
-----------------------------149742642616556--
引发此错误:
Pattern pattern = Pattern.compile(BOUNDARY_PATTERN); // "(?m)\\A-+\\d+$"
Matcher matcher = pattern.matcher(byteString);
String boundary = null;
while (matcher.find()) {
boundary = matcher.group();
contentType = "multipart/form-data; boundary=" + boundary;
}
LOG.info("Content Type = " + contentType);
@SuppressWarnings("deprecation")
org.apache.commons.fileupload.MultipartStream multipartStream =
new org.apache.commons.fileupload.MultipartStream(new ByteArrayInputStream(byteString.getBytes()), boundary.getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
multipartStream.readBodyData(bos); // throw error
byte[] byteBody = bos.toByteArray();
这里可能有什么问题?我会在这里为您提供帮助。
答案 0 :(得分:1)
该问题似乎是由于行尾不良以及检索边界的方式所致。根据RFC2046引述的SO answer语录:>
多部分实体的Content-Type字段需要一个参数“边界”。然后将边界定界符线定义为完全由两个连字符组成的行(“-”,十进制值45),后跟Content-Type中的边界参数值标头字段,可选的线性空格和终止CRLF 。
问题恰好在于两点:行类型的结尾和边界参数值之前的两个连字符。
由于您的代码无法正确显示byteString的值,因此我尝试了 LF (\n
)和 CRLF (\r\n
)行尾,看看会发生什么。
当行的坏末尾(即不是CRLF)出现在最后一个边界之前 时,似乎再现了该问题,如下所示:
String byteString=
"-----------------------------149742642616556\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n" +
"Content-Type: text/plain; charset=UTF-8\r\n" +
"\r\n" +
"test\r\n" + // <-- only \n here lead to a MalformedStreamException
"-----------------------------149742642616556--\r\n";
听起来好像MultipartStream无法解析边界的开始,因为它没有抓住上一行的右行结束(CRLF)。 因此,我使用了LF终结器,应将它们替换为CRLF终结器。
RFC告知边界定界符是两个连字符+边界参数+ CRLF。您的正则表达式不仅捕获边界参数值,还包括两个连字符。所以我替换了这部分:
// capturing group = boundary parameter value
String regexp="(?m)\\A--(-*\\d+)$";
// [...]
while (matcher.find()) {
boundary = matcher.group(1);
// [...]
}
您将在下面找到的代码可以在没有Tomcat的控制台中运行。只需commons-fileupload-1.3.3-bin.tar.gz和commons-io-2.6-bin.tar.gz。
要查看MultipartStream
解析的内容,我在bos
调用中将System.out
临时替换为readBodyData()
(如评论中所述)。
要编译:
javac Test.java -classpath ./commons-fileupload-1.3.3-bin/commons-fileupload-1.3.3.jar
要运行:
java -classpath ./commons-fileupload-1.3.3-bin/commons-fileupload-1.3.3.jar:./commons-io-2.6/commons-io-2.6.jar:. Test
import java.util.regex.*;
import java.io.*;
import org.apache.commons.fileupload.*;
public class Test {
public final static void main(String[] argv) {
String byteString=
"-----------------------------149742642616556\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n" +
"Content-Type: text/plain; charset=UTF-8\r\n" +
"\r\n" +
"test\r\n" + // <-- only \n here lead to a MalformedStreamException
"-----------------------------149742642616556--\r\n";
String regexp="(?m)\\A--(-*\\d+)$"; // edited regexp to catch the right boundary
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(byteString);
String boundary = null;
String contentType=null;
while (matcher.find()) {
boundary = matcher.group(1);
contentType = "multipart/form-data; boundary=\"" + boundary + "\"";
}
System.out.println("boundary = \"" + boundary + "\"");
@SuppressWarnings("deprecation")
org.apache.commons.fileupload.MultipartStream multipartStream =
new org.apache.commons.fileupload.MultipartStream
(new ByteArrayInputStream(byteString.getBytes()), boundary.getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
// Use the commented line instead the following one
// To see what the multipartStream is reading (for debug)
// multipartStream.readBodyData(System.out);
multipartStream.readBodyData(bos);
} catch (MultipartStream.MalformedStreamException e) {
System.out.println("Malformed Exception " + e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
byte[] byteBody = bos.toByteArray();
// Displaying the body read
for(byte c : byteBody) {
System.out.format("%c", c);
}
System.out.println();
}
}
boundary = "---------------------------149742642616556"
-----------------------------149742642616556
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain; charset=UTF-8
test
答案 1 :(得分:0)
经过一些调试后,我发现MultipartStream
将\r\n--
作为边界的前缀,因为在内容的开头我没有换行符,所以我得到了{{1} }例外,因为找不到边界。
也许是由于MultipartStream.MalformedStreamException("Stream ended unexpectedly")
版本较旧,或者是因为我正在从commons-fileupload
发送的HTTP PUT请求中读取多部分内容
在内容的开头添加换行符。