Запись изображения через URLConnection

Я пытаюсь записать изображение через HttpURLConnection.

Я умею писать текст, но у меня возникают серьезные проблемы при попытке написать изображение

Мне удалось записать на локальный HD с помощью ImageIO:

Но я пытаюсь написать изображение ImageIO по URL-адресу и не смог

URL url = new URL(uploadURL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "multipart/form-data;
                                            boundary=" + boundary);
output = new DataOutputStream(connection.getOutputStream());
output.writeBytes("--" + boundary + "\r\n");
output.writeBytes("Content-Disposition: form-data; name=\"" + FIELD_NAME + "\";
                                            filename=\"" + fileName + "\"\r\n");
output.writeBytes("Content-Type: " + dataMimeType + "\r\n");
output.writeBytes("Content-Transfer-Encoding: binary\r\n\r\n");
ImageIO.write(image, imageType, output);

uploadURL - это URL-адрес asp-страницы на сервере, который будет загружать изображение с именем файла, указанным в части "content-Disposition:".

теперь, когда я отправляю это, тогда страница asp находит запрос и находит имя файла. но не находит файл для загрузки.

Проблема в том, что при записи ImageIO по URL-адресу, какое будет имя файла, в который пишет ImageIO,

Итак, пожалуйста, помогите мне, как ImageIO напишет изображение на URLConnection и как я могу узнать имя файла, который я должен использовать на странице asp для загрузки файла.

Спасибо, что нашли время прочитать этот пост Дилип Агарвал


person agarwal_achhnera    schedule 03.02.2011    source источник


Ответы (2)


Сначала я считаю, что вы должны позвонить io.flush(), а затем io.close() после написания изображения.

Второй тип контента мне кажется странным. Похоже, вы пытаетесь отправить форму, хотя на самом деле это изображение. Я не знаю, что ожидает ваш asp, но обычно, когда я пишу код, который должен передавать файл через HTTP, я отправляю соответствующий тип контента, например. image/jpeg.

Вот, например, фрагмент кода, который я извлек из одной небольшой утилиты, которую я написал и использую в своей текущей работе:

    URL url = new URL("http://localhost:8080/handler");
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setDoInput(true);
    con.setDoOutput(true);
    con.setUseCaches(false);
    con.setRequestProperty("Content-Type", "image/jpeg");
    con.setRequestMethod("POST");
    InputStream in = new FileInputStream("c:/temp/poc/img/mytest2.jpg");
    OutputStream out = con.getOutputStream();
    copy(in, con.getOutputStream());
    out.flush();
    out.close();
    BufferedReader r = new BufferedReader(new  InputStreamReader(con.getInputStream()));


            // obviously it is not required to print the response. But you have
            // to call con.getInputStream(). The connection is really established only
            // when getInputStream() is called.
    System.out.println("Output:");
    for (String line = r.readLine(); line != null;  line = r.readLine()) {
        System.out.println(line);
    }

Я использовал здесь метод copy (), который я взял из утилит Jakarta IO. Вот код для справки:

protected static long copy(InputStream input, OutputStream output)
        throws IOException {
    byte[] buffer = new byte[12288]; // 12K
    long count = 0L;
    int n = 0;
    while (-1 != (n = input.read(buffer))) {
        output.write(buffer, 0, n);
        count += n;
    }
    return count;
}

Очевидно, что серверная сторона должна быть готова к чтению содержимого изображения непосредственно из тела POST. Надеюсь, это поможет.

person AlexR    schedule 03.02.2011
comment
на самом деле я использую апплет на стороне клиента, поэтому я не могу получить доступ к файловой системе клиента. и мне нужно создать изображение диаграммы, показанной апплетом, с помощью ImageIO (поскольку он работает во время записи в файловой системе ). поэтому мне нужно писать на URLConnection прямо из ImageIO. вот почему я спрашивал, как ImageIO будет записывать содержимое изображения как файл изображения в URLConnection и как я могу установить имя этого файла изображения или узнать имя этого файла изображения - person agarwal_achhnera; 03.02.2011
comment
con.setDoOutput(true); означает con.setRequestMethod("POST");. Также вы извлекаете OutputStream out = con.getOutputStream(); и в следующей строке снова вызываете con.getOutputStream();. Также out.close(); вызывает out.flush(); (и должен быть в блоке finally). Учитывая вашу репутацию, вы должны написать более чистый код - person Mr_and_Mrs_D; 23.09.2013
comment
Соединение действительно устанавливается только при вызове getInputStream (). - ›неправда - вы можете дать ссылку на документы? - person Mr_and_Mrs_D; 23.09.2013
comment
Спасибо . положил конец долгим поискам - person Rissmon Suresh; 24.11.2016

OP кажется забытым, но в пользу Мистера Кайта:

// main method 
URL url = new URL(uploadURL);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true); // triggers "POST"
// connection.setDoInput(true); // only if needed
connection.setUseCaches(false); // dunno
final String boundary = Long.toHexString(System.currentTimeMillis());
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
                                                                + boundary);
output = new DataOutputStream(connection.getOutputStream());
try {
     // image must be a File instance
    flushMultiPartData(image, output, boundary);
} catch (IOException e) {
    System.out.println("IOException in flushMultiPartData : " + e);
    return;
}
// ...
private void flushMultiPartData(File file, OutputStream serverOutputStream,
            String boundary) throws FileNotFoundException, IOException {
    // SEE https://stackoverflow.com/a/2793153/281545
    PrintWriter writer = null;
    try {
        // true = autoFlush, important!
        writer = new PrintWriter(new OutputStreamWriter(serverOutputStream,
                charsetForMultipartHeaders), true);
        appendBinary(file, boundary, writer, serverOutputStream);
        // End of multipart/form-data.
        writer.append("--" + boundary + "--").append(CRLF);
    } finally {
        if (writer != null) writer.close();
    }
}

private void appendBinary(File file, String boundary, PrintWriter writer,
        OutputStream output) throws FileNotFoundException, IOException {
    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append(
        "Content-Disposition: form-data; name=\"binaryFile\"; filename=\""
            + file.getName() + "\"").append(CRLF);
    writer.append("Content-Type: "
            +  URLConnection.guessContentTypeFromName(file.getName()))
            .append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    InputStream input = null;
    try {
        input = new FileInputStream(file);
        byte[] buffer = new byte[1024];
        for (int length = 0; (length = input.read(buffer)) > 0;) {
            output.write(buffer, 0, length);
        }
        output.flush(); // Important! Output cannot be closed. Close of
        // writer will close output as well.
    } finally {
        if (input != null) try {
            input.close();
        } catch (IOException logOrIgnore) {}
    }
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of
    // binary boundary.
}

Вы можете добавить сжатие Gzip - см. файл поврежден, когда я отправляю его в сервлет с помощью GZIPOutputStream для рабочего класса с или без Gzip. ImageIO здесь нет места - просто напишите байты по сети и используйте ImageIO на сервере, сколько душе угодно. На основе ответа @BalusC

person Mr_and_Mrs_D    schedule 23.09.2013