Android-日常遭遇-檔案上傳MIME協議
阿新 • • 發佈:2018-12-18
寫上傳檔案的時候,需要產生part才能讓檔案上傳成功,
而android原生並沒有提供這樣的方法,需要自己寫.首先看下mime協議
MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "AF+hwZxkNq38nq6w4liUUA" [Type: multipart/form-data] First boundary: --AF+hwZxkNq38nq6w4liUUA==\r\n Encapsulated multipart part: Data (102 bytes) Data: 2d2d41462b68775a786b4e7133386e713677346c69555541... [Length: 102] Boundary: \r\n--AF+hwZxkNq38nq6w4liUUA==\r\n Encapsulated multipart part: (application/octet-stream) Content-Disposition: form-data; name="userfile"; filename="aaa.mp4"\r\n Content-Type: application/octet-stream\r\n\r\n Data (2003015 bytes) Data: 000000206674797069736f6d0000020069736f6d69736f32... [Length: 2003015] Boundary: \r\n--AF+hwZxkNq38nq6w4liUUA==--\r\n Encapsulated multipart part:
可以看出,是由
--邊界碼
Content-Disposition-key
value
--邊界碼
...
--邊界碼--
結束
由此可以模仿出
private void postFile(PostFormBody body) throws IOException { // 說明有檔案 // 邊界標識 隨機生成 Random random = new Random(); byte[] randomBytes = new byte[16]; random.nextBytes(randomBytes); String boundary = Base64.encodeToString(randomBytes, Base64.NO_WRAP); String prefix = "--"; String lineEnd = "\r\n"; currentCallRequest.getConnection().setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); OutputStream outputStream = currentCallRequest.getConnection().getOutputStream(); DataOutputStream out = putParams(body, boundary, prefix, lineEnd, outputStream); putFile(body, boundary, prefix, lineEnd, out); out.flush(); out.close(); } @NonNull private DataOutputStream putParams(PostFormBody body, String boundary, String prefix, String lineEnd, OutputStream outputStream) throws IOException { DataOutputStream out = new DataOutputStream(outputStream); Map<String, String> queryMap = body.params; if (queryMap != null && !queryMap.isEmpty()) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : queryMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); sb.append(prefix).append(boundary).append(lineEnd); out.write(sb.toString().getBytes()); sb.append("Content-Disposition") .append(": ") .append("form-data") .append("; name=\"") .append(key) .append("\"") .append(lineEnd); sb.append("Content-Length") .append(": ") .append(value.length()) .append(lineEnd) .append(lineEnd); sb.append(value).append(lineEnd); } out.write(sb.toString().getBytes()); out.flush(); } return out; } private void putFile(PostFormBody body, String boundary, String prefix, String lineEnd, DataOutputStream out) throws IOException { StringBuilder sb = new StringBuilder(); sb.append(prefix).append(boundary).append(lineEnd); sb.append(CONTENT_DISPOSITION) .append(": ") .append("form-data") .append("; name=\"") .append(body.keyFile) .append("\"; filename=\"") .append(body.mFile.getName()) .append("\"") .append(lineEnd); sb.append( + "Content-Type: application/octet-stream").append(lineEnd); sb.append(lineEnd); out.write(sb.toString().getBytes()); out.flush(); InputStream input = new FileInputStream(body.mFile); byte[] bytes = new byte[1024]; int len = 0; while ((len = input.read(bytes)) != -1) { out.write(bytes, 0, len); } out.write(lineEnd.getBytes()); out.flush(); byte[] endData = (prefix + boundary + prefix + lineEnd).getBytes(); out.write(endData); out.flush(); input.close(); }
PostFormBody
public Map<String, String> params;
public String keyFile;
public File mFile;
private PostFormBody(Builder builder) {
params = builder.params;
keyFile = builder.keyFile;
mFile = builder.mFile;
}
這裡有一點需要注意
currentCallRequest.getConnection().setRequestProperty(CONTENT_TYPE, TYPE_FORM_DATA_NO_CHARSET + "; boundary=" + boundary);
這邊是不能有引號以及其他符號,如果有其他符號會導致檔案上傳,將資料疊加到一起.導致上傳失敗
如果是正常,則會讓協議成功
詳細封裝可以看我的github