httphandler java_java – 使用HTTPHandler上传文件

这篇博客探讨了在Java中使用HttpHandler上传文件时遇到的问题,即WebKit Boundary被写入目标文件导致文件损坏。作者提供了HTML和JavaScript代码片段,并展示了问题的示例输出。解决方案建议使用Apache Commons FileUpload库来解析multipart/form-data请求,以避免手动处理边界问题。还提供了一个使用HttpServer和HttpHandler的文件上传工作示例。

我正在尝试使用HTTPHandler上传文件(多部分表单数据).

WebKit Boundary正在写入目标文件,从而破坏文件.

输入文件可以是任何类型的文件,包括文本,zip,apk等.

码:

public void handle(HttpExchange httpExchange) throws IOException {

URI uri = httpExchange.getRequestURI();

String httpReqMethod = httpExchange.getRequestMethod();

Headers headers = httpExchange.getRequestHeaders();

InputStream inputStrm = null;

FileOutputStream destFile = null;

String contentType = ((headers.get("Content-type") != null) ? (headers.get("Content-type").toString()) : (null));

httpExchange.getRequestURI().getQuery());

Map queryParams = queryToMap(httpExchange.getRequestURI().getQuery());

Set keys= headers.keySet();

Iterator itr = keys.iterator();

while(itr.hasNext())

{

String key = (String)itr.next();

}

File file = new File(ACEConstants.WEB_SERVER_CTX_ROOT + uri.getPath()).getCanonicalFile();

String resource = uri.getPath().substring(

uri.getPath().indexOf(ACEConstants.WEB_SERVER_CTX_ROOT)+ACEConstants.WEB_SERVER_CTX_ROOT.length()+1);

if(httpReqMethod.equals(ACEConstants.HTTP_REQUEST_METHOD_POST) )

{

if(contentType != null && contentType.contains("multipart/form-data"))

{

if(resource.equals("fileUpload"))

{

inputStrm = httpExchange.getRequestBody();

destFile = new FileOutputStream(new File("D:\\"+queryParams.get("fileName")));

String contentLength = headers.get("Content-length").toString();

long fileSize = (Long.parseLong(contentLength.substring(1, contentLength.length()-1)));

int iteration = 1;

long bytesToBeRead = (fileSize > 1024) ? ((iteration * 1024)) : (inputStrm.available());

long bytesRemaining = (fileSize) - (iteration * 1024);

byte[] bytes = new byte[1024];

if(fileSize <= 1024)

{

bytes = new byte[inputStrm.available()];

inputStrm.read(bytes);

destFile.write(bytes);

}

else {

while (inputStrm.read(bytes) != -1) {

iteration++;

destFile.write(bytes);

bytesRemaining = ( fileSize - ((iteration-1) * 1024));

if (bytesRemaining >= 1024) {

bytesToBeRead = 1024;

bytes = new byte[1024];

}

else {

bytes = new byte[inputStrm.available()];

inputStrm.read(bytes);

destFile.write(bytes);

break;

}

}

}

destFile.close();

}

}

}

}

这是HTML代码

function processForm(frm)

{

var fu1 = document.getElementsByName("datafile");

var filename = fu1[0].value;

filename = filename.substring(filename.lastIndexOf("\\")+1);

alert("You selected " + filename);

frm.action = "http://localhost:64444/ACE/fileUpload?fileName="+filename;

return true;

}

Please specify a file, or a set of files:

这里出了什么问题?

非常感谢帮助.

编辑1:

如果输入文件是包含文本的文本文件:1234567890

输出文件包含内容:

------WebKitFormBoundaryKBRUiUWrIpW9wq2j

Content-Disposition: form-data; name="textline"

------WebKitFormBoundaryKBRUiUWrIpW9wq2j

Content-Disposition: form-data; name="datafile"; filename="test.txt"

Content-Type: text/plain

1234567890

------WebKitFormBoundaryKBRUiUWrIpW9wq2j--

解决方法:

如何使用HttpHandler上传文件

文件上传到HttpHandler导致边界和其他MIME信息被写入请求内容.由于解析这些信息非常复杂且容易出错,因此可以使用Commons FileUpload,这被证明在经典的Servlet环境中非常有用.

考虑使用自定义ContextRequest的此示例.这将处理由multipart / form-data添加到请求体中的边界的所有解析,同时仍允许您保留HttpHandler接口.

主要思想包括实现一个自己的ContextRequest版本来处理HttpHandler中提供的数据:

public HttpHandlerRequestContext implements RequestContext {

private HttpExchange http;

public HttpHandlerRequestContext(HttpExchange http) {

this.http = http;

}

@Override

public String getCharacterEncoding() {

//Need to figure this out yet

return "UTF-8";

}

@Override

public int getContentLength() {

//tested to work with 0 as return. Deprecated anyways

return 0;

}

@Override

public String getContentType() {

//Content-Type includes the boundary needed for parsing

return http.getRequestHeaders().getFirst("Content-type");

}

@Override

public InputStream getInputStream() throws IOException {

//pass on input stream

return http.getRequestBody();

}

}

供参考:这是列出接收文件的工作示例.

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.InetSocketAddress;

import java.util.List;

import java.util.Map.Entry;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.RequestContext;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.sun.net.httpserver.HttpExchange;

import com.sun.net.httpserver.HttpHandler;

import com.sun.net.httpserver.HttpServer;

public class HttpServerTest {

public static void main(String[] args) throws Exception {

HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);

server.createContext("/fileupload", new MyHandler());

server.setExecutor(null); // creates a default executor

server.start();

}

static class MyHandler implements HttpHandler {

@Override

public void handle(final HttpExchange t) throws IOException {

for(Entry> header : t.getRequestHeaders().entrySet()) {

System.out.println(header.getKey() + ": " + header.getValue().get(0));

}

DiskFileItemFactory d = new DiskFileItemFactory();

try {

ServletFileUpload up = new ServletFileUpload(d);

List result = up.parseRequest(new RequestContext() {

@Override

public String getCharacterEncoding() {

return "UTF-8";

}

@Override

public int getContentLength() {

return 0; //tested to work with 0 as return

}

@Override

public String getContentType() {

return t.getRequestHeaders().getFirst("Content-type");

}

@Override

public InputStream getInputStream() throws IOException {

return t.getRequestBody();

}

});

t.getResponseHeaders().add("Content-type", "text/plain");

t.sendResponseHeaders(200, 0);

OutputStream os = t.getResponseBody();

for(FileItem fi : result) {

os.write(fi.getName().getBytes());

os.write("\r\n".getBytes());

System.out.println("File-Item: " + fi.getFieldName() + " = " + fi.getName());

}

os.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

标签:java,file-upload,multipartform-data,httphandler

来源: https://codeday.me/bug/20190727/1556954.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值