採用的架構是透過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所擷取的畫面
沒有留言:
張貼留言
留個話吧:)