diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java index 4ecd1ad1..ed1acf21 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java @@ -33,6 +33,14 @@ public class UploadTarget extends AbsTarget { taskEntity = new UploadTaskEntity(entity); } + /** + * 设置userAgent + */ + public UploadTarget setUserAngent(@NonNull String userAgent) { + taskEntity.userAgent = userAgent; + return this; + } + /** * 设置上传路径 * diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java index 50e7a013..07818b8d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java @@ -30,6 +30,7 @@ public class UploadTaskEntity extends ITaskEntity { public String attachment; //文件上传需要的key public String contentType = "multipart/form-data"; //上传的文件类型 public String charset = "utf-8"; + public String userAgent = "User-Agent"; /** * 文件上传表单 diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java index 702c2ba7..ce9abc61 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java @@ -26,7 +26,6 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.HttpURLConnection; -import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Set; @@ -36,21 +35,19 @@ import java.util.UUID; * Created by Aria.Lao on 2017/2/9. * 上传工具 */ -final class UploadUtil implements Runnable { +public class UploadUtil implements Runnable { private static final String TAG = "UploadUtil"; private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成 private final String PREFIX = "--", LINE_END = "\r\n"; private UploadEntity mUploadEntity; private UploadTaskEntity mTaskEntity; private IUploadListener mListener; - private PrintWriter mWriter; - private OutputStream mOutputStream; private HttpURLConnection mHttpConn; private long mCurrentLocation = 0; private boolean isCancel = false; private boolean isRunning = false; - UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) { + public UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) { mTaskEntity = taskEntity; CheckUtil.checkUploadEntity(taskEntity.uploadEntity); mUploadEntity = taskEntity.uploadEntity; @@ -81,15 +78,16 @@ final class UploadUtil implements Runnable { mListener.onPre(); - URL url = null; + URL url; try { url = new URL(mTaskEntity.uploadUrl); mHttpConn = (HttpURLConnection) url.openConnection(); mHttpConn.setUseCaches(false); mHttpConn.setDoOutput(true); mHttpConn.setDoInput(true); - mHttpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); - mHttpConn.setRequestProperty("User-Agent", "CodeJava Agent"); + mHttpConn.setRequestProperty("Content-Type", + mTaskEntity.contentType + "; boundary=" + BOUNDARY); + mHttpConn.setRequestProperty("User-Agent", mTaskEntity.userAgent); //mHttpConn.setRequestProperty("Range", "bytes=" + 0 + "-" + "100"); //内部缓冲区---分段上传防止oom mHttpConn.setChunkedStreamingMode(1024); @@ -100,17 +98,18 @@ final class UploadUtil implements Runnable { mHttpConn.setRequestProperty(key, mTaskEntity.headers.get(key)); } - mOutputStream = mHttpConn.getOutputStream(); - mWriter = new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskEntity.charset), true); + OutputStream outputStream = mHttpConn.getOutputStream(); + PrintWriter writer = + new PrintWriter(new OutputStreamWriter(outputStream, mTaskEntity.charset), true); //添加文件上传表单字段 keys = mTaskEntity.formFields.keySet(); for (String key : keys) { - addFormField(key, mTaskEntity.formFields.get(key)); + addFormField(writer, key, mTaskEntity.formFields.get(key)); } mListener.onStart(uploadFile.length()); - addFilePart(mTaskEntity.attachment, uploadFile); - Log.d(TAG, finish() + ""); + uploadFile(writer, outputStream, mTaskEntity.attachment, uploadFile); + Log.d(TAG, finish(writer) + ""); } catch (IOException e) { e.printStackTrace(); fail(); @@ -122,56 +121,55 @@ final class UploadUtil implements Runnable { } private void fail() { - //mWriter.flush(); - //mWriter.close(); mListener.onFail(); } /** * 添加文件上传表单字段 */ - private void addFormField(String name, String value) { - mWriter.append(PREFIX).append(BOUNDARY).append(LINE_END); - mWriter.append("Content-Disposition: form-data; name=\"") + private void addFormField(PrintWriter writer, String name, String value) { + writer.append(PREFIX).append(BOUNDARY).append(LINE_END); + writer.append("Content-Disposition: form-data; name=\"") .append(name) .append("\"") .append(LINE_END); - mWriter.append("Content-Type: text/plain; charset=") + writer.append("Content-Type: text/plain; charset=") .append(mTaskEntity.charset) .append(LINE_END); - mWriter.append(LINE_END); - mWriter.append(value).append(LINE_END); - mWriter.flush(); + writer.append(LINE_END); + writer.append(value).append(LINE_END); + writer.flush(); } /** * 上传文件 * - * @param fieldName 文件上传attachment + * @param attachment 文件上传attachment * @throws IOException */ - private void addFilePart(String fieldName, File uploadFile) throws IOException { - String fileName = uploadFile.getName(); - mWriter.append(PREFIX).append(BOUNDARY).append(LINE_END); - mWriter.append("Content-Disposition: form-data; name=\"") - .append(fieldName) + private void uploadFile(PrintWriter writer, OutputStream outputStream, String attachment, + File uploadFile) throws IOException { + writer.append(PREFIX).append(BOUNDARY).append(LINE_END); + writer.append("Content-Disposition: form-data; name=\"") + .append(attachment) .append("\"; filename=\"") - .append(fileName) + .append(mTaskEntity.uploadEntity.getFileName()) .append("\"") .append(LINE_END); - mWriter.append("Content-Type: ") - .append(URLConnection.guessContentTypeFromName(fileName)) + writer.append("Content-Type: ") + //.append(URLConnection.guessContentTypeFromName(mTaskEntity.uploadEntity.getFileName())) + .append(mTaskEntity.contentType) .append(LINE_END); - mWriter.append("Content-Transfer-Encoding: binary").append(LINE_END); - mWriter.append(LINE_END); - mWriter.flush(); + writer.append("Content-Transfer-Encoding: binary").append(LINE_END); + writer.append(LINE_END); + writer.flush(); FileInputStream inputStream = new FileInputStream(uploadFile); - byte[] buffer = new byte[1024]; - int bytesRead = -1; + byte[] buffer = new byte[4096]; + int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { mCurrentLocation += bytesRead; - mOutputStream.write(buffer, 0, bytesRead); + outputStream.write(buffer, 0, bytesRead); if (isCancel) { break; } @@ -179,11 +177,11 @@ final class UploadUtil implements Runnable { mListener.onProgress(mCurrentLocation); } - mOutputStream.flush(); - mOutputStream.close(); + outputStream.flush(); + outputStream.close(); inputStream.close(); - mWriter.append(LINE_END); - mWriter.flush(); + writer.append(LINE_END); + writer.flush(); isRunning = false; if (isCancel) { mListener.onCancel(); @@ -197,26 +195,28 @@ final class UploadUtil implements Runnable { * * @throws IOException */ - private String finish() throws IOException { + private String finish(PrintWriter writer) throws IOException { StringBuilder response = new StringBuilder(); - mWriter.append(LINE_END).flush(); - mWriter.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END); - mWriter.close(); + writer.append(LINE_END).flush(); + writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END); + writer.close(); int status = mHttpConn.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader(mHttpConn.getInputStream())); - String line = null; + String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); mHttpConn.disconnect(); + } else { + Log.w(TAG, "state_code = " + status); } - mWriter.flush(); - mWriter.close(); + writer.flush(); + writer.close(); return response.toString(); } diff --git a/Aria/src/main/java/com/arialyy/aria/util/MultipartUtility.java b/Aria/src/main/java/com/arialyy/aria/util/MultipartUtility.java new file mode 100644 index 00000000..3b1d9843 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/MultipartUtility.java @@ -0,0 +1,151 @@ +package com.arialyy.aria.util; + +import java.io.BufferedReader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; + +/** + * This utility class provides an abstraction layer for sending multipart HTTP + * POST requests to a web server. + * @author www.codejava.net + * + */ +public class MultipartUtility { + private final String boundary; + private static final String LINE_FEED = "\r\n"; + private HttpURLConnection httpConn; + private String charset; + private OutputStream outputStream; + private PrintWriter writer; + + /** + * This constructor initializes a new HTTP POST request with content type + * is set to multipart/form-data + * @param requestURL + * @param charset + * @throws IOException + */ + public MultipartUtility(String requestURL, String charset) + throws IOException { + this.charset = charset; + + // creates a unique boundary based on time stamp + boundary = "===" + System.currentTimeMillis() + "==="; + + URL url = new URL(requestURL); + httpConn = (HttpURLConnection) url.openConnection(); + httpConn.setUseCaches(false); + httpConn.setDoOutput(true); // indicates POST method + httpConn.setDoInput(true); + httpConn.setRequestProperty("Content-Type", + "multipart/form-data; boundary=" + boundary); + //httpConn.setRequestProperty("User-Agent", "CodeJava Agent"); + //httpConn.setRequestProperty("Test", "Bonjour"); + outputStream = httpConn.getOutputStream(); + writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), + true); + } + + /** + * Adds a form field to the request + * @param name field name + * @param value field value + */ + public void addFormField(String name, String value) { + writer.append("--" + boundary).append(LINE_FEED); + writer.append("Content-Disposition: form-data; name=\"" + name + "\"") + .append(LINE_FEED); + writer.append("Content-Type: text/plain; charset=" + charset).append( + LINE_FEED); + writer.append(LINE_FEED); + writer.append(value).append(LINE_FEED); + writer.flush(); + } + + /** + * Adds a upload file section to the request + * @param fieldName name attribute in + * @param uploadFile a File to be uploaded + * @throws IOException + */ + public void addFilePart(String fieldName, File uploadFile) + throws IOException { + String fileName = uploadFile.getName(); + writer.append("--" + boundary).append(LINE_FEED); + writer.append( + "Content-Disposition: form-data; name=\"" + fieldName + + "\"; filename=\"" + fileName + "\"") + .append(LINE_FEED); + writer.append( + "Content-Type: " + + URLConnection.guessContentTypeFromName(fileName)) + .append(LINE_FEED); + writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED); + writer.append(LINE_FEED); + writer.flush(); + + FileInputStream inputStream = new FileInputStream(uploadFile); + byte[] buffer = new byte[4096]; + int bytesRead = -1; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.flush(); + inputStream.close(); + + writer.append(LINE_FEED); + writer.flush(); + } + + /** + * Adds a header field to the request. + * @param name - name of the header field + * @param value - value of the header field + */ + public void addHeaderField(String name, String value) { + writer.append(name + ": " + value).append(LINE_FEED); + writer.flush(); + } + + /** + * Completes the request and receives response from the server. + * @return a list of Strings as response in case the server returned + * status OK, otherwise an exception is thrown. + * @throws IOException + */ + public List finish() throws IOException { + List response = new ArrayList(); + + writer.append(LINE_FEED).flush(); + writer.append("--" + boundary + "--").append(LINE_FEED); + writer.close(); + + // checks server's status code first + int status = httpConn.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + BufferedReader reader = new BufferedReader(new InputStreamReader( + httpConn.getInputStream())); + String line = null; + while ((line = reader.readLine()) != null) { + response.add(line); + } + reader.close(); + httpConn.disconnect(); + } else { + throw new IOException("Server returned non-OK status: " + status); + } + + return response; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java index 74021577..c75b2cda 100644 --- a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java +++ b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java @@ -1,11 +1,17 @@ package com.arialyy.simple.upload; +import android.os.Bundle; import android.os.Handler; import android.os.Message; import butterknife.Bind; import butterknife.OnClick; import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.upload.IUploadListener; +import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.core.upload.UploadTaskEntity; +import com.arialyy.aria.core.upload.UploadUtil; +import com.arialyy.aria.util.MultipartUtility; import com.arialyy.frame.util.FileUtil; import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.T; @@ -13,7 +19,10 @@ import com.arialyy.simple.R; import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.databinding.ActivityUploadMeanBinding; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; +import java.io.File; +import java.io.IOException; import java.lang.ref.WeakReference; +import java.util.List; /** * Created by Aria.Lao on 2017/2/9. @@ -59,12 +68,85 @@ public class UploadActivity extends BaseActivity { return R.layout.activity_upload_mean; } + @Override protected void init(Bundle savedInstanceState) { + super.init(savedInstanceState); + //test(); + } + + private void test(){ + String charset = "UTF-8"; + File uploadFile1 = new File("/sdcard/Download/test.zip"); + String requestURL = "http://172.18.104.50:8080/UploadActivity/sign_file"; + + try { + MultipartUtility multipart = new MultipartUtility(requestURL, charset); + + //multipart.addHeaderField("Test-Header", "Header-Value"); + + multipart.addFilePart("file", uploadFile1); + List response = multipart.finish(); + + System.out.println("SERVER REPLIED:"); + + for (String line : response) { + System.out.println(line); + } + } catch (IOException ex) { + System.err.println(ex); + } + + //UploadEntity entity = new UploadEntity(); + //entity.setFilePath("/sdcard/Download/test.zip"); + //entity.setFileName("test.pdf"); + //UploadTaskEntity taskEntity = new UploadTaskEntity(entity); + //taskEntity.uploadUrl = "http://172.18.104.50:8080/UploadActivity/sign_file"; + //taskEntity.attachment = "file"; + //UploadUtil util = new UploadUtil(taskEntity, new IUploadListener() { + // long fileSize = 0; + // + // @Override public void onPre() { + // + // } + // + // @Override public void onStart(long fileSize) { + // this.fileSize = fileSize; + // } + // + // @Override public void onResume(long resumeLocation) { + // + // } + // + // @Override public void onStop(long stopLocation) { + // + // } + // + // @Override public void onProgress(long currentLocation) { + // int p = (int) (currentLocation * 100 / fileSize); + // mPb.setProgress(p); + // } + // + // @Override public void onCancel() { + // + // } + // + // @Override public void onComplete() { + // + // } + // + // @Override public void onFail() { + // + // } + //}); + //util.start(); + } + @OnClick(R.id.upload) void upload() { - Aria.upload(this) - .load(FILE_PATH) - .setUploadUrl("http://172.18.104.50:8080/upload/sign_file") - .setAttachment("file") - .start(); + //Aria.upload(this) + // .load(FILE_PATH) + // .setUploadUrl("http://172.18.104.50:8080/upload/sign_file") + // .setAttachment("file") + // .start(); + test(); } @OnClick(R.id.stop) void stop() {