问题描述
我有一个休息web服务,需要一个POST梅托德与多部分消息:
I have a rest webservice that takes a POST metod with multipart message:
@Path("transferFile")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_XML)
public String multipartTest(com.sun.jersey.multipart.MultiPart data) {
try {
// get first body part (index 0)
BodyPart bp = multiPart.getBodyParts().get(0);
etc..
现在我试图写一个Java客户端。我开始用一个简单的客户端球衣:
鉴于plaincopy到clipboardprint?
Now I am trying to write a java client for that. I started with a simple jersey client:view plaincopy to clipboardprint?
MultiPart multiPart = new MultiPart();
multiPart.bodyPart( new BodyPart(wavestream,MediaType.APPLICATION_OCTET_STREAM_TYPE));
Client c = Client.create();
WebResource r = c.resource("http://127.0.0.1:8080/webapp:);
response=r.path("transferFile").type(MediaType.MULTIPART_FORM_DATA).accept(MediaType.APPLICATION_XML).post(String.class, multiPart);
这个伟大的工程 - 一切正常。不过,我需要这个客户端在Android上工作,我有使用该平台上的球衣麻烦。所以我用正常的方式在Android上发送多部分消息:
This works great - everything is ok. However I need this client working on Android and I have trouble with using jersey on that platform. So I used the normal way to send multipart message on android:
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter("http.socket.timeout", new Integer(90000)); // 90 second
HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/webapp/transferFile");
httpPost.setHeader("Content-Type", MediaType.MULTIPART_FORM_DATA );
//tried with and without base64
byte [] encodedWavestream = Base64.encodeBytesToBytes(wavestream);
InputStream ins = new ByteArrayInputStream(encodedWavestream);
InputStreamBody body = new InputStreamBody(ins, "test" );
int send = ins.available();
MultipartEntity requestContent = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE );
requestContent.addPart("stream", body);
httpPost.setEntity(requestContent);
HttpResponse Response = client.execute(httpPost);
这是这给从服务器一个恼人的响应:
An this gives an annoying response from the server :
HTTP Status 400 - Bad Request
The request sent by the client was syntactically incorrect (Bad Request).
我检查服务器的日志文件,但里面空空如也。所以,我不知道这是什么错误的由来。我已经写了一个简单的HTML页面后公式和'的multipart / form-data的Content-Type和它也可以!从soapUI的自动生成的请求也适用!为什么我的客户端不能正常工作?任何人可以帮助?
I check the server log files but there is nothing there. So I don't know what's the origin of this error. I have wrote a simple html page with a post formula and 'multipart/form-data' content-type and it also works! An auto-generated request from soapUI also works! Why my client does not work? Can anybody help?
推荐答案
有错误是在泽西岛。请参见。
There is bug in Jersey. See Chunked encoding problem.
出现此问题只为少数客户端(iOS版,Android版)。
This problem appears only for few clients (iOS, Android).
如果您设置的内容类型应用程序/八位字节流,然后泽西MessageWriter应用程序/八位字节流将设置内容长度和
不发为分块传输方法。
If you set the Content-Type to application/octet-stream, then the Jersey MessageWriter for the application/octet-stream will set the Content-Length andnot send as chunked transport method.
有是Jersey客户端
There is solution for Jersey Client:
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 32 * 1024);
不过,这并不为的iOS的或Android的客户端工作。
所以,我测试的Apache文件上传。 Threre是另一个错误:流意外结束
But it doesn't work for the iOS's or Android's client.So I tested Apache File Upload. Threre was another bug: "Stream ended unexpectedly".
只有 可以上传文件正确的所有客户机。
这是我的code:
Only Oreilly upload can upload file correct for all clients.This is my code:
public Object[] getParametersAndFiles(HttpServletRequest request) throws IOException {
log.debug("OreillyUpload");
Properties params = new Properties();
LinkedHashMap files = new LinkedHashMap();
File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
MultipartParser mp = new MultipartParser(request, 1*1024*1024); // 10MB
Part part;
while ((part = mp.readNextPart()) != null) {
String name = part.getName();
if (part.isParam()) {
// it's a parameter part
ParamPart paramPart = (ParamPart) part;
String value = paramPart.getStringValue();
params.put(name, value);
log.debug("param; name=" + name + ", value=" + value);
}
else if (part.isFile()) {
// it's a file part
FilePart filePart = (FilePart) part;
String fileName = filePart.getFileName();
if (fileName != null) {
// the part actually contained a file
File file = new File(tempDirectory,fileName);
long size = filePart.writeTo(file);
files.put(name, file);
log.debug("file; name=" + name + "; filename=" + fileName +
", filePath=" + filePart.getFilePath() +
", content type=" + filePart.getContentType() +
", size=" + size);
}
else {
// the field did not contain a file
log.debug("file; name=" + name + "; EMPTY");
}
}
}
return new Object[] {params, files};
}
这是泽西服务器code(警告所有泽西上传anotations(如为@FormDataParam),应删除):
And this is Jersey Server code (warning all Jersey Upload anotations (like as "@FormDataParam") should be removed):
@POST
@Path("uploadMarkup")
@Produces(MediaType.APPLICATION_JSON)
// @Consumes(MediaType.MULTIPART_FORM_DATA)
//// public void uploadMarkup(
// public JSONWithPadding uploadMarkup(
// @FormDataParam("markupFile") InputStream markupFile,
// @FormDataParam("markupFile") FormDataContentDisposition details,
// @FormDataParam("slideNum") int slideNum) {
public JSONWithPadding uploadMarkup(@Context HttpServletRequest request) {
Object[] data = uploadService.getParametersAndFiles(request);
...
}
这篇关于HttpClient的和MultipartEntity主场迎战新泽西多部分和Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!