W moim App Engine backend Mam metodę, która pobiera obraz z Google Cloud Storage
Wysyłanie danych obrazowych do android aplikacji z App Engine
@ApiMethod(
name = "getProfileImage",
path = "image",
httpMethod = ApiMethod.HttpMethod.GET)
public Image getProfileImage(@Named("imageName")String imageName){
try{
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential.getApplicationDefault();
Storage.Builder storageBuilder = new Storage.Builder(httpTransport,new JacksonFactory(),credential);
Storage storage = storageBuilder.build();
Storage.Objects.Get getObject = storage.objects().get("mybucket", imageName);
ByteArrayOutputStream out = new ByteArrayOutputStream();
// If you're not in AppEngine, download the whole thing in one request, if possible.
getObject.getMediaHttpDownloader().setDirectDownloadEnabled(false);
getObject.executeMediaAndDownloadTo(out);
byte[] oldImageData = out.toByteArray();
out.close();
ImagesService imagesService = ImagesServiceFactory.getImagesService();
return ImagesServiceFactory.makeImage(oldImageData);
}catch(Exception e){
logger.info("Error getting image named "+imageName);
}
return null;
}
problem mam jest w jaki sposób uzyskać dane obrazu, gdy zgłoszę to w mojej aplikacji na Androida?
Ponieważ nie można zwrócić prymitywów z silnika aplikacji, przekonwertowałem go na Image
, dzięki czemu mógłbym wywołać w mojej aplikacji getImageData()
, aby uzyskać bajt [].
Jednak obiekt Obraz, który został zwrócony do aplikacji, nie jest tym samym, co obiekt w silniku aplikacji, więc nie ma metody getImageData().
Jak mogę uzyskać dane obrazu do mojej aplikacji na Androida?
Jeśli utworzę obiekt o zmiennej bajtowej [], ustawię zmienną byte [] z danymi ciągu i zwrócę obiekt z metody, która będzie działać?
Aktualizacja
Obraz zostaje wysłany z aplikacji na Androida. (Kod ten może lub nie może być poprawne, ja nie debugowany go jeszcze)
@WorkerThread
public String startResumableSession(){
try{
File file = new File(mFilePath);
long fileSize = file.length();
file = null;
String sUrl = "https://www.googleapis.com/upload/storage/v1/b/lsimages/o?uploadType=resumable&name="+mImgName;
URL url = new URL(sUrl);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestProperty("Authorization","");
urlConnection.setRequestProperty("X-Upload-Content-Type","image/png");
urlConnection.setRequestProperty("X-Upload-Content-Length",String.valueOf(fileSize));
urlConnection.setRequestMethod("POST");
if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
return urlConnection.getHeaderField("Location");
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
private long sendNextChunk(String sUrl,File file,long skip){
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 524287;
long totalBytesSent = 0;
try{
long fileSize = file.length();
FileInputStream fileInputStream = new FileInputStream(file);
skip = fileInputStream.skip(skip);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
totalBytesSent = skip + bufferSize;
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
try {
while (bytesRead > 0) {
try {
URL url = new URL(sUrl);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setChunkedStreamingMode(524287);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Content-Type","image/png");
urlConnection.setRequestProperty("Content-Length",String.valueOf(bytesRead));
urlConnection.setRequestProperty("Content-Range", "bytes "+String.valueOf(skip)+"-"+String.valueOf(totalBytesSent)+"/"+String.valueOf(fileSize));
DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
outputStream.write(buffer, 0, bufferSize);
int code = urlConnection.getResponseCode();
if(code == 308){
String range = urlConnection.getHeaderField("Range");
return Integer.parseInt(range.split("-")[1]);
}else if(code == HttpURLConnection.HTTP_CREATED){
return -1;
}
outputStream.flush();
outputStream.close();
outputStream = null;
} catch (OutOfMemoryError e) {
e.printStackTrace();
// response = "outofmemoryerror";
// return response;
return -1;
}
fileInputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
// response = "error";
// return response;
return -1;
}
}catch(Exception e){
e.printStackTrace();
}
return -1;
}
Edit 2:
Widocznie jej nie jasne dla ludzi, że używam punktów końcowych w moim Android app
Zwykle używam Python więc nie wiem, to zrobić w Javie, ale może po prostu wrócić url obraz wygenerowany profil z Google Cloud Storage zamiast zwracać tablicę bajtów. W ten sposób można buforować adres URL profilu, aby uniknąć jego odbudowy przez cały czas. –
As @ Maël powiedział, że nie powinieneś przenosić całego obrazu przez stos (ze względu na wydajność, ale także w celu zmniejszenia kosztów).Czy tworzysz typ obrazu? Jeśli tak, czy możesz opublikować jego źródło? –
@ BenoîtSauvère obrazy pochodzą z aplikacji na Androida, zaktualizowałem pytanie tym kodem. Aby uzyskać adres URL obrazu, muszę mimo wszystko pobrać dane obrazu? Zasadniczo chciałbym pobrać dane obrazu dwukrotnie, raz na serwerze, aby uzyskać adres URL do wyświetlania i ponownie w aplikacji klienckiej. Czy nie byłoby to bardziej nieefektywne (kosztowne) niż tylko uzyskiwanie danych obrazu z serwera? Gdy aplikacja na Androida otrzyma dane obrazu, mój plan polegał na buforowaniu obrazu lokalnie (zapisanie go na dysku), aby nie musiała go już odzyskiwać. – tyczj