Fixed file upload
This commit is contained in:
parent
8ad285cd61
commit
99973b7c98
8 changed files with 61 additions and 51 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|
|
||||||
|
|
@ -157,14 +157,16 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
* Skips over the closest boundary
|
* Skips over the closest boundary
|
||||||
*/
|
*/
|
||||||
public void next() throws IOException {
|
public void next() throws IOException {
|
||||||
|
// read data until we find the next boundary or get to the end of the stream
|
||||||
|
if (buf_bound_pos < 0) {
|
||||||
|
while (fillBuffer() >= 0 && buf_bound_pos < 0)
|
||||||
|
buf_pos = buf_end;
|
||||||
|
}
|
||||||
|
|
||||||
if (buf_bound_pos >= 0){ // is boundary in buffer?
|
if (buf_bound_pos >= 0){ // is boundary in buffer?
|
||||||
buf_pos += boundary.length;
|
buf_pos += boundary.length;
|
||||||
searchNextBoundary();
|
searchNextBoundary();
|
||||||
}
|
}
|
||||||
else { // read data until we find the next boundary or get to the end of the stream
|
|
||||||
while (buf_bound_pos < 0 && fillBuffer() >= 0)
|
|
||||||
buf_pos = buf_end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -236,9 +238,6 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
// Do we need to fill the buffer
|
// Do we need to fill the buffer
|
||||||
if(buf_pos < buf_end-boundary.length)
|
if(buf_pos < buf_end-boundary.length)
|
||||||
return 0;
|
return 0;
|
||||||
// is there any data available
|
|
||||||
if(leftover <= 0 && super.available() <= 0)
|
|
||||||
return -1; // EOF
|
|
||||||
|
|
||||||
// Move the end of the buffer to the start to not miss any split boundary
|
// Move the end of the buffer to the start to not miss any split boundary
|
||||||
if (leftover > 0 && buf_pos != 0)
|
if (leftover > 0 && buf_pos != 0)
|
||||||
|
|
@ -247,12 +246,16 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
buf_end = leftover;
|
buf_end = leftover;
|
||||||
|
|
||||||
// Copy in new data from the stream
|
// Copy in new data from the stream
|
||||||
int n = super.read(buffer, buf_end, buffer.length-buf_end);
|
int n = -1;
|
||||||
if (n >= 0)
|
if (super.available() > 0) { // is there any data available
|
||||||
buf_end = buf_end + n;
|
n = super.read(buffer, buf_end, buffer.length - buf_end);
|
||||||
|
if (n >= 0)
|
||||||
|
buf_end = leftover = buf_end + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update boundary position
|
||||||
searchNextBoundary();
|
searchNextBoundary();
|
||||||
return ((n < 0 && this.available() > 0) ? 0 : n);
|
return ((leftover > 0 && n < 0) ? 0 : n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -260,18 +263,16 @@ public class BufferedBoundaryInputStream extends FilterInputStream{
|
||||||
*/
|
*/
|
||||||
private void searchNextBoundary(){
|
private void searchNextBoundary(){
|
||||||
// No need to check for boundary if buffer is smaller than the boundary length
|
// No need to check for boundary if buffer is smaller than the boundary length
|
||||||
if (this.available() >= boundary.length) {
|
for (int i = buf_pos; i <= buf_end-boundary.length; i++) {
|
||||||
for (int i = buf_pos; i < buf_end; i++) {
|
for (int b = 0; b < boundary.length; b++) {
|
||||||
for (int b = 0; b < boundary.length; b++) {
|
if (buffer[i + b] != boundary[b])
|
||||||
if (buffer[i + b] != boundary[b])
|
break;
|
||||||
break;
|
else if (b == boundary.length - 1) {
|
||||||
else if (b == boundary.length - 1) {
|
buf_bound_pos = i;
|
||||||
buf_bound_pos = i;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
buf_bound_pos = -1;
|
buf_bound_pos = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,7 @@ package zutil.net.http;
|
||||||
|
|
||||||
import zutil.net.http.HttpPrintStream.HttpMessageType;
|
import zutil.net.http.HttpPrintStream.HttpMessageType;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.*;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -54,7 +51,7 @@ public class HttpClient implements AutoCloseable{
|
||||||
|
|
||||||
// Response variables
|
// Response variables
|
||||||
private HttpHeaderParser rspHeader;
|
private HttpHeaderParser rspHeader;
|
||||||
private BufferedInputStream rspReader;
|
private InputStream rspStream;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -127,10 +124,10 @@ public class HttpClient implements AutoCloseable{
|
||||||
request.close();
|
request.close();
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
if(rspHeader != null || rspReader != null) // Close previous request
|
if(rspHeader != null || rspStream != null) // Close previous request
|
||||||
this.close();
|
this.close();
|
||||||
rspReader = new BufferedInputStream(conn.getInputStream());
|
rspStream = new BufferedInputStream(conn.getInputStream());
|
||||||
rspHeader = new HttpHeaderParser( rspReader );
|
rspHeader = new HttpHeaderParser(rspStream);
|
||||||
|
|
||||||
return rspHeader;
|
return rspHeader;
|
||||||
}
|
}
|
||||||
|
|
@ -138,15 +135,15 @@ public class HttpClient implements AutoCloseable{
|
||||||
public HttpHeaderParser getResponseHeader(){
|
public HttpHeaderParser getResponseHeader(){
|
||||||
return rspHeader;
|
return rspHeader;
|
||||||
}
|
}
|
||||||
public BufferedInputStream getResponseReader(){
|
public InputStream getResponseInputStream(){
|
||||||
return rspReader;
|
return rspStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if(rspReader != null)
|
if(rspStream != null)
|
||||||
rspReader.close();
|
rspStream.close();
|
||||||
rspReader = null;
|
rspStream = null;
|
||||||
rspHeader = null;
|
rspHeader = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ public class HttpHeaderParser {
|
||||||
|
|
||||||
// First line
|
// First line
|
||||||
if (readStatusLine) {
|
if (readStatusLine) {
|
||||||
if( (line= IOUtil.readLine(in)) != null && !line.isEmpty() )
|
if( (line=IOUtil.readLine(in)) != null && !line.isEmpty() )
|
||||||
parseStatusLine(header, line);
|
parseStatusLine(header, line);
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -102,7 +102,7 @@ public class HttpHeaderParser {
|
||||||
* @param header the header object where the cookies will be stored.
|
* @param header the header object where the cookies will be stored.
|
||||||
* @param statusLine the status line String
|
* @param statusLine the status line String
|
||||||
*/
|
*/
|
||||||
public static void parseStatusLine(HttpHeader header, String statusLine){
|
private static void parseStatusLine(HttpHeader header, String statusLine){
|
||||||
// Server Response
|
// Server Response
|
||||||
if( statusLine.startsWith("HTTP/") ){
|
if( statusLine.startsWith("HTTP/") ){
|
||||||
header.setIsRequest(false);
|
header.setIsRequest(false);
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,11 @@ public class HttpServer extends ThreadedTCPNetworkServer{
|
||||||
header.getHeader("Content-Type") != null &&
|
header.getHeader("Content-Type") != null &&
|
||||||
header.getHeader("Content-Type").contains("application/x-www-form-urlencoded")) {
|
header.getHeader("Content-Type").contains("application/x-www-form-urlencoded")) {
|
||||||
// Reads the post data size
|
// Reads the post data size
|
||||||
int post_data_length = Integer.parseInt(header.getHeader("Content-Length"));
|
int postDataLength = Integer.parseInt(header.getHeader("Content-Length"));
|
||||||
// read the data
|
// read the data
|
||||||
StringBuilder tmpBuff = new StringBuilder();
|
StringBuilder tmpBuff = new StringBuilder();
|
||||||
// read the data
|
// read the data
|
||||||
for (int i = 0; i < post_data_length; i++) {
|
for (int i = 0; i < postDataLength; i++) {
|
||||||
tmpBuff.append((char) in.read());
|
tmpBuff.append((char) in.read());
|
||||||
}
|
}
|
||||||
// get the variables
|
// get the variables
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,6 @@ public class MultipartFileField implements MultipartField{
|
||||||
this.filename = headers.get("filename");
|
this.filename = headers.get("filename");
|
||||||
this.contentType = headers.get(HEADER_CONTENT_TYPE);
|
this.contentType = headers.get(HEADER_CONTENT_TYPE);
|
||||||
this.in = in;
|
this.in = in;
|
||||||
|
|
||||||
if (contentType != null && !contentType.equalsIgnoreCase("application/octet-stream"))
|
|
||||||
logger.warning("Unsupported Content-Type: "+contentType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -72,20 +72,13 @@ public class MultipartParser implements Iterable<MultipartField>{
|
||||||
parseDelimiter(header.getHeader("Content-type")),
|
parseDelimiter(header.getHeader("Content-type")),
|
||||||
Long.parseLong(header.getHeader("Content-Length")));
|
Long.parseLong(header.getHeader("Content-Length")));
|
||||||
}
|
}
|
||||||
/* public MultipartParser(HttpServletRequest req) throws IOException {
|
|
||||||
this(req.getInputStream(),
|
|
||||||
parseDelimiter(req.getHeader("Content-type")),
|
|
||||||
req.getContentLength());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
private static String parseDelimiter(String contentTypeHeader){
|
private static String parseDelimiter(String contentTypeHeader){
|
||||||
String delimiter = contentTypeHeader.split(" *; *")[1];
|
String delimiter = contentTypeHeader.split(" *; *")[1];
|
||||||
delimiter = delimiter.split(" *= *")[1];
|
delimiter = delimiter.split(" *= *")[1];
|
||||||
return delimiter;
|
return delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public long getContentLength(){
|
public long getContentLength(){
|
||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,27 @@ public class BufferedBoundaryInputStreamTest {
|
||||||
assertFalse(in.hasNext());
|
assertFalse(in.hasNext());
|
||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
|
public void read_largeDataOnlyNext() throws IOException {
|
||||||
|
String data = "#aaaaaaaaaaaa#aa#aaaaaaaaaaaaaaa#";
|
||||||
|
StringInputStream inin = new StringInputStream(data);
|
||||||
|
BufferedBoundaryInputStream in = new BufferedBoundaryInputStream(inin, 10);
|
||||||
|
in.setBoundary("#");
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
for (int i=0; i<12; ++i)
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
|
||||||
|
in.next();
|
||||||
|
for (int i=0; i<15; ++i)
|
||||||
|
assertEquals('a', in.read());
|
||||||
|
assertEquals(-1, in.read());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
public void readArr_largeData() throws IOException {
|
public void readArr_largeData() throws IOException {
|
||||||
String data = "aaaaaaaaaaaa#aa#aaaaaaaaaaaaaaa#";
|
String data = "aaaaaaaaaaaa#aa#aaaaaaaaaaaaaaa#";
|
||||||
StringInputStream inin = new StringInputStream(data);
|
StringInputStream inin = new StringInputStream(data);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue