Загрузка файлов с помощью HTTPHandler
Я пытаюсь загрузить файл (multi part form data) с помощью 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();
          }
        } 
      }
    }
Вот HTML-код
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        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;
        }
    </script>
</head>
<body>
<form name="myForm" enctype="multipart/form-data" method="post" acceptcharset="UTF-8" onsubmit="processForm(this);">
    <p>
        Please specify a file, or a set of files:<br>
        <input type="file" name="datafile" size="40">
    </p>
    <div>
        <input type="submit" value="Send">
    </div>
</form>
</body>
</html>
Что здесь не так? Помощь была бы очень признательна.
Править 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--
2 ответа:
Как загружать файлы с помощью 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<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(); } } } }