Как отправить данные изображения на сервер с Android - PullRequest
4 голосов
/ 03 ноября 2011

Я пытаюсь написать приложение для Android, которое будет делать снимок, помещать данные (byte []) в объект вместе с некоторыми метаданными и отправлять их на сервер AppEngine, где они будут сохраняться в хранилище данных как клякса. Я действительно не хочу сохранять изображение в виде файла на Android (если это не является абсолютно необходимым). Я искал решения, но ничего ясного или достаточно конкретного не нашлось. Мои вопросы:

  1. как мне опубликовать объект в моем сервлете? В частности, как правильно сериализовать объект и получить сериализованный вывод в HttpPost или что-то подобное.
  2. Как только я сохраню блоб в хранилище данных, как я смогу получить его как изображение для отображения на веб-странице?

Примеры кода были бы очень полезны. Кроме того, если подход, который я выбрал, слишком сложен или проблематичен, предложите другие подходы (например, сохранение изображения в виде файла, публикация на сервере, а затем удаление).

Ответы [ 5 ]

8 голосов
/ 16 марта 2012

Вам просто нужно сделать Http-FileUpload, который в особом случае POST.Нет необходимости кодировать файл.Нет необходимости использовать специальный lib / jar. Нет необходимости сохранять объект на диск (независимо от того, как это делает следующий пример)

Вы найдете очень хорошее объяснение команды Http-Command и как вашего особого фокуса "загрузить "под

с помощью java.net.URLConnection для запуска и обработки HTTP-запросов

Ниже приведен пример загрузки файла (смотрите" Отправить двоичный файл ") иМожно добавить некоторые сопутствующие данные либо


String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.

URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
    OutputStream output = connection.getOutputStream();
    writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!

    // Send normal param.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"param\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF);
    writer.append(param).append(CRLF).flush();

    // Send text file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF).flush();
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new InputStreamReader(new FileInputStream(textFile), charset));
        for (String line; (line = reader.readLine()) != null;) {
            writer.append(line).append(CRLF);
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
    }
    writer.flush();

    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: " +     URLConnection.guessContentTypeFromName(binaryFile.getName()).append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    InputStream input = null;
    try {
        input = new FileInputStream(binaryFile);
        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.

    // End of multipart/form-data.
    writer.append("--" + boundary + "--").append(CRLF);
} finally {
    if (writer != null) writer.close();
}

Относительно второй части вашего вопроса.При успешной загрузке файла (я использую общие файлы apache), нет ничего сложного в том, чтобы доставлять BLOB-объекты в виде изображений.

Это способ приема файла в сервлете

public void doPost(HttpServletRequest pRequest, HttpServletResponse pResponse)
        throws ServletException, IOException {
    ServletFileUpload upload = new ServletFileUpload();

    try {
        FileItemIterator iter = upload.getItemIterator (pRequest);

        while (iter.hasNext()) {
            FileItemStream item = iter.next();

            String fieldName = item.getFieldName();

                InputStream stream = item.openStream();
            ....
                stream.close();
            }
    ...

И этот код дает изображение

public void doGet (HttpServletRequest pRequest, HttpServletResponse pResponse)  throws IOException {

    try {
        Blob img = (Blob) entity.getProperty(propImg);

        pResponse.addHeader ("Content-Disposition", "attachment; filename=abc.png");
        pResponse.addHeader ("Cache-Control", "max-age=120");

        String enc = "image/png";
        pResponse.setContentType (enc);
        pResponse.setContentLength (img.getBytes().length);
        OutputStream out = pResponse.getOutputStream ();
        out.write (img.getBytes());
        out.close();

Я надеюсь, что фрагменты этого кода помогут ответить на ваши вопросы

6 голосов
/ 03 ноября 2011

1.Вы можете закодировать байт [] в base64, используя:

http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html

2. Отправьте эти данные с помощью запроса HTTP POST в ваш сервлет AppEngine.

3.Настройте AppEngine для приема сервлета.

4. После этого вы можете сохранить его в хранилище данных или в Blobstore.-Я предпочитаю хранилище BLOB-объектов для таких вещей.

5.Декодировать строку сервера base64.

6. Оттуда вам нужно будет разрезать вашу строку на более мелкие кусочки изаписать каждый фрагмент в хранилище.

Вот некоторый код для записи в хранилище.

byte[] finalImageArray = null;

    try {
        finalImageArray = Base64.decode(finalImageData.getBytes()); //finalImageData is the string retrieved from the HTTP POST
    } catch (Base64DecoderException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


    try{
        FileService fileService = FileServiceFactory.getFileService();

        AppEngineFile file = fileService.createNewBlobFile("image/png");

        FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);

        int steps = (int) Math.floor(finalImageArray.length/1000);
        int current = 0;
        for(int i = 0; i < 1000; i++){
            writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, steps+current)));
            current = current + steps;
        }
        writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, finalImageArray.length)));  //The reason it's cut up like this is because you can't write the complete string in one go.

        writeChannel.closeFinally();

        blobKey = fileService.getBlobKey(file);

        if(blobKey == null)
            blobKey = retryBloBKey(file); //My own method, AppEngine tends to not return the blobKey once a while.

    }
    catch(Exception e){
        logger.log(Level.SEVERE,e.getMessage());
    }


            return blobKey.getKeyString();
  1. Напишите сервлет, в который вы получите данные изображения с помощьюkey.

  2. Наслаждайтесь прекрасным кодом:)

// Причина, по которой я сохраняю его в двоичном коде, заключается в том, что это дает мне возможность играть сизображение API, вы также можете сохранить его в формате base64.

2 голосов
/ 16 марта 2012

Поскольку код предоставляется тремя людьми, так что вы можете выбрать любой из них (или вы получите много примеров в Google).Существует три варианта: 1) сначала у вас есть изображение на вашей SD-карте

2) вы загружаете изображение с сервера, а затем отправляете

3) изображения хранятся в базе данных как blob

Наилучший подход с учетом каждого случая -

1) Если ваше изображение хранится в SDCard, просто попробуйте преобразовать в растровое изображение -> byteArray -> String и отправить на сервер

2) Если вызагружают изображения с сервера и затем отправляют на другой URL. Затем загружают все URL-хранилища изображений в DataBase Table. Позже, когда вам нужно отправить на сервер извлечение URL, загрузить изображение и сохранить в кеш-памяти. Затем аналогичным образом отправьте его на сервер и обновите кешпамять

3) Рекомендуется не хранить большое количество изображений в DB. Но если у вас есть необходимость сделать это, тогда getBlob преобразует в байтовый массив и отправляет на сервер

ОтправкаИзображение На сервер

Чтение BLOB-объектов

Чтение с SDCard

List<Integer> drawablesId = new ArrayList<Integer>();
int picIndex=12345;
 File sdDir = new File("/sdcard/pictures");
File[] sdDirFiles = sdDir.listFiles();
for(File singleFile : sdDirFiles)
{
Drawable.createFromPath(singleFile.getAbsolutePath());
/ you can create Bitmap from drawable
 }

Надеюсь, это поможет вам

1 голос
/ 13 марта 2012

Не совсем уверен, что это именно то, что вам нужно, но при этом изображение будет отправлено так же, как ваш браузер отправил бы изображение как часть формы. Вам нужно будет загрузить httmime-4.1.3.jar и добавить его в качестве библиотеки ссылок в вашем проекте.

        Bitmap bm;//whatever bitmap you are trying to send
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bm.compress(CompressFormat.JPEG, 75, bos);
        byte[] data = bos.toByteArray();
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost postRequest = new HttpPost("http://yourwebsite.com/whatever");
        ByteArrayBody bab = new ByteArrayBody(data, "image name");
        MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
        reqEntity.addPart("photo", bab);//"photo" is the name of the field that the image is submitted as.
        postRequest.setEntity(reqEntity);
        try {
            HttpResponse response = httpClient.execute(postRequest);
        } catch (ClientProtocolException e) {
            Log.e("asdf", e.getMessage(), e);
        } catch (IOException e) {
            Log.e("asdf", e.getMessage(), e);
        }
1 голос
/ 03 ноября 2011
  1. Библиотека Android Asynchronous Http предоставляет метод загрузки файлов в веб-службу. Я использовал его в своих проектах с большим успехом.

  2. Похоже, вам нужен метод веб-службы, который принимает параметр ID и возвращает файл. Вы должны хранить ваши большие двоичные объекты в таблице базы данных, индексированной с помощью идентификатора, чтобы на них можно было ссылаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...