Этим утром я написал собственный сервер на Java.В конце концов, я хочу использовать его в качестве бэкэнда для реактивного приложения, поэтому я работал над реализацией загрузки файлов.Я тестировал это с помощью простой формы HTML, которая отправляет свои данные на мой локальный компьютер.Когда я анализирую заголовки HTTP-запроса, я извлекаю Content-Length секции данных запроса (далее именуемой «телом сообщения» запроса).Иногда тело сообщения HTTP-запроса содержит имя файла и его содержимое, но чаще всего оно пустое, даже если Content-Length и Content-Type (включая границу формы) установлены правильно (ненулевая длина,Граница "--WebKitBoundary ...").Я могу обнаружить это и тайм-аут (и нет, увеличение моего тайм-аута не позволяет мне читать больше данных), но тот факт, что HTTP-запрос указывает на то, что должны быть данные, когда ничего не получено, кажется существенной проблемой.
Пост здесь , кажется, именно то, что я вижу, но на этот пост он не получил ответа.
Это класс, который я использую для чтения данных из InputStreamустановленного соединения Socket:
public class HTTPRequest {
// full request, HTTP verb + URI, meta-data, message body
public final String request, requestline, headers, data;
// regex to find the length of the message body
private static final Pattern contentlength = Pattern.compile("Content-Length\\s*:\\s*(\\d+)");
/*
* when an object is created it reads the entire HTTP request from the stream and sets its constant strings accordingly
*/
public HTTPRequest(InputStream is) throws Exception {
/*
* get everything except the message body
*/
@SuppressWarnings("resource") // closing the Scanner closes the stream, so suppressing the resource leak warning
Scanner s = new Scanner(is);
requestline = s.nextLine();
s.useDelimiter("\r\n\r\n");
headers = s.next();
// get the reported length of the message body, 0 if not present
Matcher m = contentlength.matcher(headers);
int length = 0;
if(m.find()) {
length = Integer.parseInt(m.group(1));
}
// if there is a message body, read it
if(length > 0) {
// this will contain the message bytes
byte[] b = new byte[length];
// number of bytes read, number of consecutive times I read 0 bytes
int read = 0;
int numzeros = 0;
// read until I've read the entire message
while(read < length) {
// read however many bytes are available
int numread = is.read(b, read, is.available());
read += numread;
if(numread == 0) {
numzeros++;
}else {
numzeros = 0;
}
// timeout after not getting any data for 1 second
if(numzeros > 100) {
break;
}
Thread.sleep(10);
}
data = new String(b, 0, read);
// otherwise, no message body
}else {
data = "";
}
// combine all of the parts of the request
request = requestline + "\r\n" + headers + "\r\n\r\n" + data;
}
}
и вот HTML-код, который я использовал для загрузки файла:
<head>
</head>
<body>
<form action="http://localhost:54600/api/test/test/uploadFile" method="post" enctype="multipart/form-data">
<input name="name" type="text" />
<input name="upload" type="file" />
<input type="submit" />
</form>
</body>
Это то, что я прочитал из InputStream:
POST /api/test/test/uploadFile HTTP/1.1
Host: localhost:54600
Connection: keep-alive
Content-Length: 531
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzkLQnlCjBb2a5sOP
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
, который, кроме отсутствия какого-либо тела сообщения, кажется правильным.Ранее сегодня я обнаружил, что обычно получаю тело сообщения, если загружаю уникальный файл каждый раз, когда отправляю форму (отправка одного и того же файла более одного раза имела тенденцию не иметь тела сообщения, хотя иногда это происходило).Теперь я не могу получить тело сообщения вообще.
Обновление, после написания последнего абзаца, я решил проверить еще несколько в другой вкладке.На этот раз я получил тело сообщения:
POST /api/test/test/uploadFile HTTP/1.1
Host: localhost:54600
Connection: keep-alive
Content-Length: 1162
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryErwo4zpzcDBuyDo5
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
------WebKitFormBoundaryErwo4zpzcDBuyDo5
Content-Disposition: form-data; name="name"
test_name
------WebKitFormBoundaryErwo4zpzcDBuyDo5
Content-Disposition: form-data; name="upload"; filename="hello_world.o"
Content-Type: application/octet-stream
ELF [... binary data]
------WebKitFormBoundaryErwo4zpzcDBuyDo5--
Я протестировал еще несколько в этой новой вкладке, и большую часть времени я получал данные формы, но уже видел, что они не отправляют тело сообщения дваили три раза.Кажется, что не существует четкого шаблона, когда отправка формы не включает тело сообщения.
Есть ли у кого-нибудь мысли о том, что может происходить?
Спасибо!