写上传文件的时候,需要产生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