Java Proxy Servlet для отправки файлов

Я пытаюсь использовать Panda с моим приложением GWT. Я могу загружать видео прямо на сервер Panda, используя

POST MY_PANDA_SERVER/videos/MY_VIDEO_ID/upload

Однако я хотел бы спрятать свой сервер panda за моим сервером J2EE (glassfish). Я хотел бы добиться этого:

  1. Начните загрузку в какой-нибудь сервлет на моем сервере J2EE
  2. Аутентифицировать пользователя
  3. POST файл на моем сервере Panda, все еще загружая в сервлет

В идеале я хотел бы никогда не хранить файл на сервере J2EE, а просто использовать его в качестве прокси-сервера для доступа к серверу panda.

4 ответа

Решение

Commons FileUpload хорош, но не достаточен в вашем случае. Он будет анализировать все тело в памяти перед предоставлением файловых элементов (и потоков). Вы не заинтересованы в отдельных пунктах. По сути, вы просто хотите передать тело запроса с одной стороны на другую прозрачно, не изменяя его и не сохраняя его в памяти каким-либо образом. FileUpload будет только анализировать тело запроса на некоторые "пригодные для использования" объекты Java, а HttpClient будет снова создавать только то же самое тело запроса на основе этих объектов Java. Эти объекты Java также потребляют память.

Вам не нужна библиотека для этого (или это должен быть Commons IO, чтобы заменить for петля с помощью вкладыша IOUtils#copy()). Достаточно только базовых Java NET и IO API. Вот начальный пример:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    URLConnection connection = new URL("http://your.url.to.panda").openConnection();
    connection.setDoOutput(true); // POST.
    connection.setRequestProperty("Content-Type", request.getHeader("Content-Type")); // This one is important! You may want to check other request headers and copy it as well.

    // Set streaming mode, else HttpURLConnection will buffer everything.
    int contentLength = request.getContentLength();
    if (contentLength > -1) {
        // Content length is known beforehand, so no buffering will be taken place.
        ((HttpURLConnection) connection).setFixedLengthStreamingMode(contentLength);
     } else {
        // Content length is unknown, so send in 1KB chunks (which will also be the internal buffer size).
        ((HttpURLConnection) connection).setChunkedStreamingMode(1024);
    }

    InputStream input = request.getInputStream();
    OutputStream output = connection.getOutputStream();
    byte[] buffer = new byte[1024]; // Uses only 1KB of memory!

    for (int length = 0; (length = input.read(buffer)) > 0;) {
        output.write(buffer, 0, length);
        output.flush();
    }

    output.close();
    connection.getInputStream(); // Important! It's lazily executed.
}

Лучшее решение - использовать компонент сервлета apache-camel: http://camel.apache.org/servlet.html

Вы можете использовать Apache Commons File Upload для получения файла. Затем вы можете использовать http-клиент для загрузки файла на ваш сервер panda с помощью POST. С помощью загрузки файлов Apache Commons вы можете обработать файл в памяти, так что вам не нужно его хранить.

Основываясь на ответе Энрике, я также рекомендую использовать FileUpload и HttpClient. FileUpload может дать вам поток загруженного файла:

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload();

// Parse the request
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
    FileItemStream item = iter.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (item.isFormField()) {
        System.out.println("Form field " + name + " with value "
            + Streams.asString(stream) + " detected.");
    } else {
        System.out.println("File field " + name + " with file name "
            + item.getName() + " detected.");
        // Process the input stream
        ...
    }
}

Затем вы можете использовать HttpClient или HttpComponents для выполнения POST. Вы можете найти пример здесь.

Другие вопросы по тегам