Intereting Posts
Затухание в анимации при загрузке изображения Использование Picasso Подключение SSL-разъема Android уведомляет о обновлении телефонной книги (Content Observer) Используйте постоянное уведомление, чтобы позволить пользователю вернуться к запущенному приложению Android. SDK Manager не запускает Windows 7 64-бит? Проблемы с обновлением консоли разработчика Google Play, нормально? Отправить HTTP-запрос GET с заголовком Обратный ответ asynchttpclient для Android loopj Получить onPause & onResume как события на уровне приложений / задач Запустите эмулятор ICS без кнопки меню Android – изменить название версии аромата на основе типа сборки Не можете получить градиентные фоны, чтобы хорошо выглядеть? Как создать особую частоту звука? Помещает API автозаполнения для получения координат GPS с введенного адреса Что означает «работает в потоке пользовательского интерфейса» для onPostExecute ()?

Использование blobstore с конечной точкой Google и Android

Я разрабатываю проект Android-приложения, связанный с приложением, используя плагин eclipse. Один из аспектов приложения – позволить пользователю Alpha отправлять фотографии пользователю Bravo. Для этого у меня есть следующая настройка:

Пользовательская публикация Alpha:

  • Отправить изображение на сервер приложений с помощью конечных точек
  • Сервер хранит изображение в хранилище blob
  • Сервер хранит blobkey в хранилище данных

Пользователь Bravo получает:

  • Сервер получает blobkey из хранилища данных
  • Сервер получает изображение с помощью клавиши blob
  • Сервер отправляет изображение в приложение для Android с использованием конечных точек

Эта настройка занимает два (2) минуты, когда приложение для Android отправляет изображение, когда я вижу его в язве blob. Излишне говорить, что это совершенно неприемлемо.

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

public static BlobKey toBlobstore(Blob imageData) throws FileNotFoundException, FinalizationException, LockException, IOException { if (null == imageData) return null; // Get a file service FileService fileService = FileServiceFactory.getFileService(); // Create a new Blob file with mime-type "image/png" AppEngineFile file = fileService.createNewBlobFile("image/jpeg");// png // Open a channel to write to it boolean lock = true; FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock); // This time we write to the channel directly writeChannel.write(ByteBuffer.wrap (imageData.getBytes())); // Now finalize writeChannel.closeFinally(); return fileService.getBlobKey(file); } 

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

Solutions Collecting From Web of "Использование blobstore с конечной точкой Google и Android"

Я расскажу, как я это делаю. Я не использую google-cloud-endpoints, а просто собственный собственный api на основе отдыха, но в любом случае это должна быть одна и та же идея.

Я выложу шаг за шагом с кодом, надеюсь, это будет ясно. Вы просто адаптируете способ отправки своих запросов для использования конечных точек вместо того, чтобы делать это более общим, как в этом примере. Я включаю некоторые шаблоны, но исключаю try / catch, проверку ошибок и т. Д. Для краткости.

Шаг 1 (клиент)

Первый клиент запрашивает URL-адрес загрузки с сервера:

 HttpClient httpclient = new DefaultHttpClient(); HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000); //Timeout Limit HttpGet httpGet = new HttpGet("http://example.com/blob/getuploadurl"); response = httpclient.execute(httpGet); 

Шаг 2 (сервер)

На стороне сервера сервлет запроса на загрузку будет выглядеть примерно так:

 String blobUploadUrl = blobstoreService.createUploadUrl("/blob/upload"); res.setStatus(HttpServletResponse.SC_OK); res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.print(blobUploadUrl); out.flush(); out.close(); 

Обратите внимание на аргумент createUploadUrl. Здесь клиент будет перенаправлен после завершения фактической загрузки. Здесь вы будете обрабатывать сохранение blobkey и / или обслуживающего URL-адреса и возвращать его клиенту. Вам нужно будет отобразить сервлет на этот URL-адрес, который будет обрабатывать шаг 4

Шаг 3 (клиент). Вернуться к клиенту еще раз, чтобы отправить фактический файл на URL-адрес загрузки, используя URL-адрес, возвращенный с шага 2.

 HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(uploadUrlReturnedFromStep2); FileBody fileBody = new FileBody(thumbnailFile); MultipartEntity reqEntity = new MultipartEntity(); reqEntity.addPart("file", fileBody); httppost.setEntity(reqEntity); HttpResponse response = httpclient.execute(httppost) 

Как только этот запрос будет отправлен на сервлет на шаге 2, он будет перенаправлен на сервлет, указанный вами в createUploadUrl() ранее

Шаг 4 (сервер)

Назад на сервер: это сервлет, обрабатывающий URL-адрес, отображаемый в blob/upload . Мы вернем blobkey и обслуживаем URL-адрес клиенту в объекте json:

 List<BlobKey> blobs = blobstoreService.getUploads(req).get("file"); BlobKey blobKey = blobs.get(0); ImagesService imagesService = ImagesServiceFactory.getImagesService(); ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey); String servingUrl = imagesService.getServingUrl(servingOptions); res.setStatus(HttpServletResponse.SC_OK); res.setContentType("application/json"); JSONObject json = new JSONObject(); json.put("servingUrl", servingUrl); json.put("blobKey", blobKey.getKeyString()); PrintWriter out = res.getWriter(); out.print(json.toString()); out.flush(); out.close(); 

Шаг 5 (клиент)

Мы получим blobkey и обслуживающий URL из json, а затем отправим его вместе с идентификатором пользователя и т. Д., Чтобы сохранить его в объекте хранилища данных.

 JSONObject resultJson = new JSONObject(resultJsonString); String blobKey = resultJson.getString("blobKey"); String servingUrl = resultJson.getString("servingUrl"); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("userId", userId)); nameValuePairs.add(new BasicNameValuePair("blobKey",blobKey)); nameValuePairs.add(new BasicNameValuePair("servingUrl",servingUrl)); HttpClient httpclient = new DefaultHttpClient(); HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000); HttpPost httppost = new HttpPost(url); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); // Continue to store the (immediately available) serving url in local storage f.ex 

Шаг 6 (сервер) На самом деле, сохраняя все в хранилище данных (используя в этом примере объективирование)

 final String userId = req.getParameter("userId"); final String blobKey = req.getParameter("blobKey"); final String servingUrl = req.getParameter("servingUrl"); ExampleEntity entity = new ExampleEntity(); entity.setUserId(userId); entity.setBlobKey(blobKey); entity.setServingUrl(servingUrl); ofy().save().entity(entity); 

Надеюсь, это упростит ситуацию. Если кто-то хочет отредактировать ответ, чтобы использовать конечные точки облака вместо этого более общего примера, не стесняйтесь 🙂

Об обслуживающем URL-адресе

Сервисный URL – отличный способ подавать изображения вашим клиентам, потому что он может динамически масштабировать изображения на лету. Например, вы можете отправлять меньшие изображения своим пользователям LDPI, просто добавив =sXXX в конец обслуживающего URL. Где XXX – размер пикселя самого большого размера вашего изображения. Вы полностью избегаете своих экземпляров и платите только за пропускную способность, а пользователь загружает только то, что ей нужно.

PS!

Должно быть возможно остановиться на шаге 4 и просто сохранить его прямо там, пройдя по userId f.ex на шаге 3. Любые параметры должны быть отправлены на шаг 4, но я не получил этого, чтобы работать, так что это Как я это делаю в данный момент, поэтому я делюсь этим так, так как знаю, что это работает.

Я использовал ответ на этот вопрос для создания собственной системы, использующей конечные точки AppEngine. В отличие от сообщений выше, я хочу иметь чистый API, который напрямую передает изображение (в виде байтового массива) в конечную точку Google, а загрузка в BlobstorageService выполняется на стороне сервера. Преимущество этого в том, что у меня есть атомный API. Недостатком, очевидно, является загрузка на сервер, а также тяжелые операции сортировки на клиенте.

Android – загрузка, масштабирование и сериализация изображения и загрузка в конечные точки

 void uploadImageBackground(Bitmap bitmap) throws IOException { // Important! you wanna rescale your bitmap (eg with Bitmap.createScaledBitmap) // as with full-size pictures the base64 representation would not fit in memory // encode bitmap into byte array (very resource-wasteful!) ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); bitmap.recycle(); bitmap = null; stream = null; // Note: We encode ourselves, instead of using image.encodeImageData, as this would throw // an 'Illegal character '_' in base64 content' exception // See: http://stackoverflow.com/questions/22029170/upload-photos-from-android-app-to-google-cloud-storage-app-engine-illegal-char String base64 = Base64.encodeToString(byteArray, Base64.DEFAULT); byteArray = null; // Upload via AppEngine Endpoint (ImageUploadRequest is a generated model) ImageUploadRequest image = new ImageUploadRequest(); image.setImageData(base64); image.setFileName("picture.png"); image.setMimeType("image/png"); App.getMyApi().setImage(image).execute(); } 

Endpoint API – Загрузить изображение в BlobstorageService

 @ApiMethod( name = "setImage", path = "setImage", httpMethod = ApiMethod.HttpMethod.POST ) public void saveFoodImageForUser(ImageUploadRequest imageRequest) throws IOException { assertNotEmpty(userId, "userId"); assertNotNull(imageRequest, "imageRequest"); // create blob url BlobstorageService blobService = BlobstoreServiceFactory.getBlobstoreService(); String uploadUrl = blobService.createUploadUrl("/blob/upload"); // create multipart body containing file HttpEntity requestEntity = MultipartEntityBuilder.create() .addBinaryBody("file", imageRequest.getImageData(), ContentType.create(imageRequest.getMimeType()), imageRequest.getFileName()) .build(); // Post request to BlobstorageService // Note: We cannot use Apache HttpClient, since AppEngine only supports Url-Fetch // See: https://cloud.google.com/appengine/docs/java/sockets/ URL url = new URL(uploadUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.addRequestProperty("Content-length", requestEntity.getContentLength() + ""); connection.addRequestProperty(requestEntity.getContentType().getName(), requestEntity.getContentType().getValue()); requestEntity.writeTo(connection.getOutputStream()); // BlobstorageService will forward to /blob/upload, which returns our json String responseBody = IOUtils.toString(connection.getInputStream()); if(connection.getResponseCode() < 200 || connection.getResponseCode() >= 400) { throw new IOException("HTTP Status " + connection.getResponseCode() + ": " + connection.getHeaderFields() + "\n" + responseBody); } // parse BlopUploadServlet's Json response ImageUploadResponse response = new Gson().fromJson(responseBody, ImageUploadResponse.class); // save blobkey and serving url ... } 

Сервлет, который обрабатывает обратный вызов из BlobstorageService

 public class BlobUploadServlet extends HttpServlet { @Override public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { BlobstorageService blobService = BlobstoreServiceFactory.getBlobstoreService(); List<BlobKey> blobs = blobService.getUploads(req).get("file"); if(blobs == null || blobs.isEmpty()) throw new IllegalArgumentException("No blobs given"); BlobKey blobKey = blobs.get(0); ImagesService imagesService = ImagesServiceFactory.getImagesService(); ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey); String servingUrl = imagesService.getServingUrl(servingOptions); res.setStatus(HttpServletResponse.SC_OK); res.setContentType("application/json"); // send simple json response (ImageUploadResponse is a POJO) ImageUploadResponse result = new ImageUploadResponse(); result.setBlobKey(blobKey.getKeyString()); result.setServingUrl(servingUrl); PrintWriter out = res.getWriter(); out.print(new Gson().toJson(result)); out.flush(); out.close(); } } 

Осталось только привязать /blob/upload к UploadBlobServlet.

Примечание . Это не работает, когда AppEngine работает локально (если выполняется локально, то POST в BlobstorageService всегда будет возвращать 404 NOT FOUND)

Поскольку я попытался сделать много способов сделать службу обратного вызова в api конечной точки, я отменяю это aproach. Тем не менее, я мог бы решить эту проблему, сделав параллельный сервлет конечной точке api, ему нужно только определить сервер класса и добавить его в конфигурацию web.xml. Здесь мое решение:

1 Enpoint Service для получения URL для загрузки: тогда сервис coudl будет защищен clientId

 @ApiMethod(name = "getUploadURL", httpMethod = HttpMethod.GET) public Debug getUploadURL() { String blobUploadUrl = blobstoreService.createUploadUrl("/update"); Debug debug = new Debug(); debug.setData(blobUploadUrl); return debug; } 

2. Теперь клиент может позвонить в конечную точку для получения URL-адреса для загрузки:
Может быть, некоторые вроде этого (для android использовать вашу клиентскую библиотеку enpoint тоже):

 gapi.client.debugendpoint.getUploadURL().execute(); 

3. Следующим шагом является отсылка к URL-адресу, указанному на последнем шаге: вы можете сделать это с помощью httpClient android, опять же, в моем случае мне нужно загрузить из Интернета, тогда я использую форму и обратный вызов события onChangeFile () для Получить uploadurl (используя шаг 3), затем, когда он ответит изменить параметры формы «action» и «codeId», прежде чем кто-то решит, нажмите кнопку «Отправить»:

 <form id="submitForm" action="put_here_uploadUrl" method="post" enctype="multipart/form-data"> <input type="file" name="image" onchange="onChangeFile()"> <input type="text" name="codeId" value='put_here_some_dataId'> <input type="submit" value="Submit"></form> 

4 Наконец, класс сервлетов paralele:

 @SuppressWarnings("serial") public class Update extends HttpServlet{ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { String userId = req.getParameter("codeId"); List<BlobKey> blobs = BSF.getService().getUploads(req).get("image"); BlobKey blobKey = blobs.get(0); ImagesService imagesService = ImagesServiceFactory.getImagesService(); ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey); String servingUrl = imagesService.getServingUrl(servingOptions); resp.setStatus(HttpServletResponse.SC_OK); resp.setContentType("application/json"); JSONObject json = new JSONObject(); try { json.put("imageUrl", servingUrl); json.put("codeId", "picture_of_"+userId); json.put("blobKey", blobKey.getKeyString()); } catch (JSONException e){ e.printStackTrace(); } PrintWriter out = resp.getWriter(); out.print(json.toString()); out.flush(); out.close(); } } 

И добавьте в web.xml, где com.apppack – пакет обновления класса

 <servlet> <servlet-name>update</servlet-name> <servlet-class>com.apppack.Update</servlet-class> </servlet> <servlet-mapping> <servlet-name>update</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>