通过 URLConnection 将音频文件从客户端传输到 Http 服务器
Transfer Audio-File from Client to Http Server via URLConnection
我目前正在学校从事一个编程项目。我需要将音频文件(MIDI 格式)从客户端成功发送到 Http 服务器。我自己已经尝试过这样做,并在互联网和 Whosebug 论坛上做了很多研究。目前可以从客户端发送文件到服务器端,但是在服务器端无法播放音频文件。
客户端代码如下:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
){
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
writer.append(CRLF).flush();
writer.append("--" + boundary + "--").append(CRLF).flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode);
}
}
服务器端代码如下:
int FILE_SIZE = Integer.MAX_VALUE-2;
int bytesRead = 0;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
byte[] mybytearray = new byte[FILE_SIZE];
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if(!f.exists()){
f.createNewFile();
}
InputStream input = t.getRequestBody();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = input.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do{
bytesRead = input.read(mybytearray, current, mybytearray.length-current);
if(bytesRead >= 0){
current += bytesRead;
}
}while(bytesRead>-1);
bos.write(mybytearray,0,current);
bos.flush();
fos.close();
bos.close();
t.sendResponseHeaders(200, 0);
input.close();
我现在很绝望,因为我找不到解决这个问题的方法。我需要使用 HTTP 服务器,但不需要使用 TCP 协议(现在通过流使用)。我想过 ftp 的解决方案,所以我不需要先将文件转换为字节数组。我认为问题就在那里。服务器无法从字节数组正确创建音频文件(midi 文件)。如果你们中有人知道解决方案。请问,我需要你的帮助 :D
你好,Gizpo
所以我对此事进行了更深入的研究。我发现了几个问题:
- 您正在混合基于二进制和基于字符的 I/O。当你在客户端侥幸逃脱时,服务器很难处理这个问题。
- 您忘记指定要发送到服务器的文件的大小。在服务器端,您无法知道(除非有人事先告诉您)(传入文件的)大小。
我编辑了你的代码并得出了这个:
客户:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Length: " + uploadFile.length()).append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println("Response code: [" + responseCode + "]");
}
}
服务器:
@Override
public void handle(HttpExchange t) throws IOException {
String CRLF = "\r\n";
int fileSize = 0;
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if (!f.exists()) {
f.createNewFile();
}
InputStream input = t.getRequestBody();
String nextLine = "";
do {
nextLine = readLine(input, CRLF);
if (nextLine.startsWith("Content-Length:")) {
fileSize =
Integer.parseInt(
nextLine.replaceAll(" ", "").substring(
"Content-Length:".length()
)
);
}
System.out.println(nextLine);
} while (!nextLine.equals(""));
byte[] midFileByteArray = new byte[fileSize];
int readOffset = 0;
while (readOffset < fileSize) {
int bytesRead = input.read(midFileByteArray, readOffset, fileSize);
readOffset += bytesRead;
}
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(FILE_TO_RECEIVED));
bos.write(midFileByteArray, 0, fileSize);
bos.flush();
t.sendResponseHeaders(200, 0);
}
private static String readLine(InputStream is, String lineSeparator)
throws IOException {
int off = 0, i = 0;
byte[] separator = lineSeparator.getBytes("UTF-8");
byte[] lineBytes = new byte[1024];
while (is.available() > 0) {
int nextByte = is.read();
if (nextByte < -1) {
throw new IOException(
"Reached end of stream while reading the current line!");
}
lineBytes[i] = (byte) nextByte;
if (lineBytes[i++] == separator[off++]) {
if (off == separator.length) {
return new String(
lineBytes, 0, i-separator.length, "UTF-8");
}
}
else {
off = 0;
}
if (i == lineBytes.length) {
throw new IOException("Maximum line length exceeded: " + i);
}
}
throw new IOException(
"Reached end of stream while reading the current line!");
}
我目前正在学校从事一个编程项目。我需要将音频文件(MIDI 格式)从客户端成功发送到 Http 服务器。我自己已经尝试过这样做,并在互联网和 Whosebug 论坛上做了很多研究。目前可以从客户端发送文件到服务器端,但是在服务器端无法播放音频文件。
客户端代码如下:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
){
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
writer.append(CRLF).flush();
writer.append("--" + boundary + "--").append(CRLF).flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println(responseCode);
}
}
服务器端代码如下:
int FILE_SIZE = Integer.MAX_VALUE-2;
int bytesRead = 0;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
byte[] mybytearray = new byte[FILE_SIZE];
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if(!f.exists()){
f.createNewFile();
}
InputStream input = t.getRequestBody();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = input.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do{
bytesRead = input.read(mybytearray, current, mybytearray.length-current);
if(bytesRead >= 0){
current += bytesRead;
}
}while(bytesRead>-1);
bos.write(mybytearray,0,current);
bos.flush();
fos.close();
bos.close();
t.sendResponseHeaders(200, 0);
input.close();
我现在很绝望,因为我找不到解决这个问题的方法。我需要使用 HTTP 服务器,但不需要使用 TCP 协议(现在通过流使用)。我想过 ftp 的解决方案,所以我不需要先将文件转换为字节数组。我认为问题就在那里。服务器无法从字节数组正确创建音频文件(midi 文件)。如果你们中有人知道解决方案。请问,我需要你的帮助 :D
你好,Gizpo
所以我对此事进行了更深入的研究。我发现了几个问题:
- 您正在混合基于二进制和基于字符的 I/O。当你在客户端侥幸逃脱时,服务器很难处理这个问题。
- 您忘记指定要发送到服务器的文件的大小。在服务器端,您无法知道(除非有人事先告诉您)(传入文件的)大小。
我编辑了你的代码并得出了这个:
客户:
private static void sendPOST() throws IOException{
final int mid = 1;
final String POST_URL = "http://localhost:8080/musiker/hörprobe?mid="+mid;
final File uploadFile = new File("C://Users//Felix Ulbrich//Desktop//EIS Prototype MIDIs//Pop//BabyOneMoreTime.mid");
String boundary = Long.toHexString(System.currentTimeMillis());
String CRLF = "\r\n";
String charset = "UTF-8";
URLConnection connection = new URL(POST_URL).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
try (
OutputStream output = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output, charset), true);
) {
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + uploadFile.getName() + "\"").append(CRLF);
writer.append("Content-Length: " + uploadFile.length()).append(CRLF);
writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(uploadFile.getName())).append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
Files.copy(uploadFile.toPath(), output);
output.flush();
int responseCode = ((HttpURLConnection) connection).getResponseCode();
System.out.println("Response code: [" + responseCode + "]");
}
}
服务器:
@Override
public void handle(HttpExchange t) throws IOException {
String CRLF = "\r\n";
int fileSize = 0;
String FILE_TO_RECEIVED = "C://root//m"+musikerid+"hp"+(hörprobenzaehler+1)+".mid";
File f = new File(FILE_TO_RECEIVED);
if (!f.exists()) {
f.createNewFile();
}
InputStream input = t.getRequestBody();
String nextLine = "";
do {
nextLine = readLine(input, CRLF);
if (nextLine.startsWith("Content-Length:")) {
fileSize =
Integer.parseInt(
nextLine.replaceAll(" ", "").substring(
"Content-Length:".length()
)
);
}
System.out.println(nextLine);
} while (!nextLine.equals(""));
byte[] midFileByteArray = new byte[fileSize];
int readOffset = 0;
while (readOffset < fileSize) {
int bytesRead = input.read(midFileByteArray, readOffset, fileSize);
readOffset += bytesRead;
}
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream(FILE_TO_RECEIVED));
bos.write(midFileByteArray, 0, fileSize);
bos.flush();
t.sendResponseHeaders(200, 0);
}
private static String readLine(InputStream is, String lineSeparator)
throws IOException {
int off = 0, i = 0;
byte[] separator = lineSeparator.getBytes("UTF-8");
byte[] lineBytes = new byte[1024];
while (is.available() > 0) {
int nextByte = is.read();
if (nextByte < -1) {
throw new IOException(
"Reached end of stream while reading the current line!");
}
lineBytes[i] = (byte) nextByte;
if (lineBytes[i++] == separator[off++]) {
if (off == separator.length) {
return new String(
lineBytes, 0, i-separator.length, "UTF-8");
}
}
else {
off = 0;
}
if (i == lineBytes.length) {
throw new IOException("Maximum line length exceeded: " + i);
}
}
throw new IOException(
"Reached end of stream while reading the current line!");
}