上传文件
开始想用apache的开源库获取文件,但是失败了,要么文件不全,要么就完全为空,还是自己写。
文件上传请求头的部分内容
contentType:multipart/form-data; boundary=----WebKitFormBoundaryHpUAY0qCryu0Oc7o
我们需要获取boundary 后面的数据,主要作用是标识文件在流中的范围。当然了,这个boundary是会变的,每次都要重新获取。
请求头之后就是发送的数据(以一个文件为例)
第一行
------WebKitFormBoundaryHpUAY0qCryu0Oc7o
第二行
Content-Disposition: form-data; name="file"; filename="ic_excel.xml" filename:ic_excel.xml
第三行
Content-Type: text/xml
第四行
\r\n\
倒数第四行\
\r\n
倒数第三行
------WebKitFormBoundaryHpUAY0qCryu0Oc7o
倒数第二行
ic_excel.xml\
倒数第一行\
------WebKitFormBoundaryHpUAY0qCryu0Oc7o--
也就是说我们需要按照行的方式来读取,以免错过这些boundary,又不能够使用Java提供的readLine,在二进制文件几乎没有换行,我们的字节数组是盛不下一行的。
private LineData getLineData(InputStream inputStream, int capacity) {
byte[] bytes = new byte[capacity];
int index = 0;
try {
while (true) {
int current = inputStream.read();
if (current == '\r') {
//检查下一个是否是\n
int next = inputStream.read();
bytes[index++] = (byte) current;
bytes[index++] = (byte) next;
if (next == '\n') {
//是\n,是一个crlf换行,退出循环
break;
} else if (next == -1) {
//因为是-1,所以退出while 不会添加换行,基本不会出现这种情况,可以根据自己需要抛出异常
index--;
break;
} //current 是正常的一个\r
} else if (current == -1) {//因为是-1,所以退出while 不会添加换行,基本不会出现这种情况,可以根据自己需要抛出异常
break;
} else
bytes[index++] = (byte) current;
if (index >= capacity - 1) {//不够下一次的\r\n了
break;
}
}
return new LineData(bytes, index);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
static class LineData {
byte[] bytes;
String string;
int length;
LineData(byte[] bytes, int length) {
this.bytes = bytes;
this.string = new String(bytes, 0, length);
this.length = length;
}
}
最后一个boundary(倒数第三行)的上面是一个换行(还要注意哦,所有的换行都是\r\n),所以在我们不知道下一行是不是boundary时,是不可以贸然写入文件的。
LineData lastLine = null;
while (true) {
LineData temp = getLineData(inputStream, capacity);
if (temp == null) {//出现异常
break;
}
if (temp.string.contains(first)) {
//上一行(lastLine)是crlf,这样就没有输出这个内容就退出了
break;
}
if (lastLine != null) {
bufferedOutputStream.write(lastLine.bytes, 0, lastLine.length);
}
lastLine = temp;
}
文件读取完毕之后还要检查后面的boundary,如果后面的内容不是我们预期的那样,这个文件基本就是错误的了。解决办法将这几行数据作为文件内容,继续读取,知道下一组boundary结束组合。
还可以根据文件类型,设定字节数组,比如文本文件,每行一百的都是足够的,如果是二进制文件,需要使用更长的数组。