採用的架構是透過Java Jersey + Apache HttpClient 4.3
package test;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import java.security.cert.X509Certificate;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
@Path("/vfs")
public class VFS {
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadObject(
@Context HttpServletRequest request,
@Context HttpServletResponse response,
InputStream inputStream)
throws IOException, JSONException {
String resp = null;
String uploadAPI =
"http://localhost:8080/JerseySample/services/vfs/internal_upload";
// request
URI uploadURI = null;
CloseableHttpClient httpClient = null;
HttpPost httpPost = null;
InputStreamEntity requestEntity = null;
// response
InputStream responseInputStream = null;
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// setting
uploadURI = URI.create(uploadAPI);
// httpClient = HttpClients.createDefault();
httpClient = getHttpClient();//for https
httpPost = new HttpPost();
httpPost.setURI(uploadURI);
String orginalContentType = request.getHeader("Content-Type");
//important!!
System.out.println("orginalContentType:" + orginalContentType);
httpPost.addHeader("Content-Type", orginalContentType);
int contentLen = request.getContentLength();
System.out.println("contentLen:" + contentLen);
requestEntity = new InputStreamEntity(
inputStream,
contentLen);
httpPost.setEntity(requestEntity);
try {
// do request
httpResponse = httpClient.execute(httpPost);
// get response entity
httpEntity = httpResponse.getEntity();
// responseInputStream = httpEntity.getContent();
System.out.println("status code:"
+ httpResponse.getStatusLine().getStatusCode());
resp = EntityUtils.toString(httpEntity);
} finally {
httpPost.releaseConnection();
IOUtils.closeQuietly(responseInputStream);
EntityUtils.consumeQuietly(httpEntity);
}
return resp;
}
public static CloseableHttpClient getHttpClient() {
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
builder.build(), new X509HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
@Override
public void verify(String arg0, SSLSocket arg1)
throws IOException {
}
@Override
public void verify(String arg0, X509Certificate arg1)
throws SSLException {
}
@Override
public void verify(String arg0, String[] arg1,
String[] arg2) throws SSLException {
}
});
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
} catch (NoSuchAlgorithmException | KeyStoreException
| KeyManagementException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
@POST
@Path("/internal_upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String uploadObject(
@Context HttpServletRequest request,
@Context HttpServletResponse response) throws IOException,
JSONException {
JSONObject respJSON = null;
System.out.println("upload start");
try {
// create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();
// parse request
System.out.println("parse request");
FileItemIterator iter = (FileItemIterator) upload
.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = (FileItemStream) iter.next();
String nameOfField = item.getFieldName();
InputStream inputStream = null;
if (!item.isFormField()) {
// file binary
System.out.println("File field '" + nameOfField
+ "' with file name '" + item.getName()
+ "' detected.");
// process the input stream
inputStream = item.openStream();// input stream of file from
// client
} else {
inputStream = item.openStream();
String valOfField = Streams.asString(inputStream, "UTF-8");
// form field
System.out.println("String field " + nameOfField
+ " with field value " + valOfField + " detected.");
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
System.out.println(String.format("Cannot upload file to: %s",
e.getMessage()));
}
respJSON = new JSONObject();
respJSON.put("statuscode", 200);
System.out.println("upload end");
return respJSON.toString();
}
}
可用REST client 測試upload API,之後upload api會透過Httpclient把Stream再送到internal_upload API。 先前遇到internal_upload無法正確解析boundary,關鍵在於upload api並未將request content-type送對,請參考下面程式碼:
String orginalContentType = request.getHeader("Content-Type");httpPost.addHeader("Content-Type", orginalContentType);
透過boundary才有辦法正確解析multipart/form-data。以下是透過REST Client所擷取的畫面

沒有留言:
張貼留言
留個話吧:)