Java 使用HTTPHandler上传文件

Java 使用HTTPHandler上传文件,java,file-upload,multipartform-data,httphandler,Java,File Upload,Multipartform Data,Httphandler,我正在尝试使用HTTPHandler上载文件(多部分表单数据) WebKit Boundary正在写入目标文件,从而损坏文件 输入文件可以是任何类型的文件,包括文本、zip、apk等 代码: public void handle(HttpExchange httpExchange) throws IOException { URI uri = httpExchange.getRequestURI(); String httpReqMethod = httpExchang

我正在尝试使用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<String, String> queryParams = queryToMap(httpExchange.getRequestURI().getQuery());
    Set<String> keys= headers.keySet();
    Iterator<String> 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();
          }
        } 
      }
    }
如何使用HttpHandler上载文件 文件上载到HttpHandler将导致边界和其他MIME信息写入请求内容。由于解析这些信息非常复杂且容易出错,因此可以使用在经典
Servlet
环境中被证明非常有效的方法

以定制的
ContextRequest
为例。这将处理通过
multipart/formdata
添加到请求主体中的所有边界解析,同时仍然允许您保留
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<String, List<String>> header : t.getRequestHeaders().entrySet()) {
                System.out.println(header.getKey() + ": " + header.getValue().get(0));
            }
            DiskFileItemFactory d = new DiskFileItemFactory();      

            try {
                ServletFileUpload up = new ServletFileUpload(d);
                List<FileItem> 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();
            }            
        }
    }
}
import java.io.IOException;
导入java.io.InputStream;
导入java.io.OutputStream;
导入java.net.InetSocketAddress;
导入java.util.List;
导入java.util.Map.Entry;
导入org.apache.commons.fileupload.FileItem;
导入org.apache.commons.fileupload.RequestContext;
导入org.apache.commons.fileupload.disk.DiskFileItemFactory;
导入org.apache.commons.fileupload.servlet.ServletFileUpload;
导入com.sun.net.httpserver.HttpExchange;
导入com.sun.net.httpserver.HttpHandler;
导入com.sun.net.httpserver.httpserver;
公共类HttpServerTest{
公共静态void main(字符串[]args)引发异常{
HttpServer server=HttpServer.create(新的InetSocketAddress(8000),0);
createContext(“/fileupload”,new MyHandler());
setExecutor(null);//创建默认执行器
server.start();
}
静态类MyHandler实现HttpHandler{
@凌驾
公共无效句柄(最终HttpExchange t)引发IOException{
对于(条目标题:t.getRequestHeaders().entrySet()){
System.out.println(header.getKey()+“:”+header.getValue().get(0));
}
DiskFileItemFactory d=新的DiskFileItemFactory();
试一试{
ServletFileUpload up=新的ServletFileUpload(d);
List result=up.parseRequest(新的RequestContext(){
@凌驾
公共字符串getCharacterEncoding(){
返回“UTF-8”;
}
@凌驾
public int getContentLength(){
return 0;//测试为使用0作为返回
}
@凌驾
公共字符串getContentType(){
返回t.getRequestHeaders().getFirst(“内容类型”);
}
@凌驾
公共InputStream getInputStream()引发IOException{
返回t.getRequestBody();
}
});
t、 getResponseHeaders().add(“内容类型”、“文本/普通”);
t、 发送响应负责人(200,0);
OutputStream os=t.GetResponseBy();
对于(文件项fi:结果){
write(fi.getName().getBytes());
写入(“\r\n”.getBytes());
System.out.println(“文件项:”+fi.getFieldName()+“=”+fi.getName());
}
os.close();
}捕获(例外e){
e、 printStackTrace();
}            
}
}
}

我也遇到过同样的问题,请使用Apache httpClient API解决
它是连接URL(文件上传和处理多部分表单数据)的最佳api。

请分享一些错误,所写内容。。。显示错误的内容。您要求提供多部分/表单数据,这就是您得到的结果。你查过了吗?@Jan:我如何通过HTTPExchange获得HTTPServletrequest?你没有。但您仍然可以通过创建自定义包装器来使用apache commons fileupload-请参阅我的答案。您会遇到什么错误?问题是关于接收端的-httpClient用于发送端(使用HTML的地方…)工作起来很有魅力。谢谢刚刚从FileItem.getContentType()获取了内容类型,并使用os.get()编写了内容。此解决方案不再有效。我收到此错误
无法访问HttpServletRequest
。您好@Dhruvgarg,您到底想做什么?在我的示例中,我没有使用HttpServletRequest。您可能缺少对servlet api的导入/a依赖关系?您好,我试图使用java注释实现非常简单的web框架(仅供学习),但无法手动实现表单数据逻辑。我添加了
javax.servlet api
,现在它开始工作了,很抱歉我犯了错误,我不知道servlet正在内部使用。
   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<String, List<String>> header : t.getRequestHeaders().entrySet()) {
                System.out.println(header.getKey() + ": " + header.getValue().get(0));
            }
            DiskFileItemFactory d = new DiskFileItemFactory();      

            try {
                ServletFileUpload up = new ServletFileUpload(d);
                List<FileItem> 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();
            }            
        }
    }
}