2011-04-02 9 views
7

Używam App Engine (version 1.4.3) direct write the blobstore do zapisywania zdjęć. gdy próbuję zapisać obraz, który jest większy niż 1MB otrzymuję następujący wyjątekLimit 1 MB limitu dla obiektu blobstore w Google App Engine?

com.google.apphosting.api.ApiProxy$RequestTooLargeException: The request to API call datastore_v3.Put() was too large. 

Myślałem, że limit for each object is 2GB

Oto kod Java, który przechowuje obraz

private void putInBlobStore(final String mimeType, final byte[] data) throws IOException { 
    final FileService fileService = FileServiceFactory.getFileService(); 
    final AppEngineFile file = fileService.createNewBlobFile(mimeType); 
    final FileWriteChannel writeChannel = fileService.openWriteChannel(file, true); 
    writeChannel.write(ByteBuffer.wrap(data)); 
    writeChannel.closeFinally(); 
} 
+2

wygląda jak dzielenie danych na mniejsze kawałki sprawiło podstęp. Nadal mam wyjątek, gdy próbowałem przechowywać duży rekord dataStore (który ma twardy limit 1 MB). ponieważ ślad stosu wyjątku był w innym wątku, pomyślałem, że to blobStore powoduje problemy. Google: jesteś mi winien kilka godzin debugowania –

+0

Jeśli umieściłeś stacktrace (lub przyjrzałeś się uważnie), mogliśmy pomóc. –

+0

* AKTUALIZACJA * powyższy kod wydaje się działać dla mnie. Wydaje się, że nie ma już limitu 1 mb ... – itgiawa

Odpowiedz

3

Maksymalny rozmiar obiektu to 2 GB, ale każde wywołanie interfejsu API może obsłużyć maksymalnie 1 MB. Przynajmniej do lektury, ale zakładam, że pisanie może być takie samo. Więc możesz spróbować podzielić swoje pisanie obiektu na porcje 1 MB i zobaczyć, czy to pomaga.

+0

Próbowałem podzielić pismo na kilka wywołań writeChannel.write, ale otrzymałem te same wyniki. –

+0

Co to znaczy "każde wywołanie API może obsłużyć maksymalnie 1 MB"? który interfejs API? czy to oznacza 1 MB na żądanie (mojej aplikacji)? –

+0

Nie, przypuszczam, że oznacza to mniej więcej każde wywołanie funkcji, a nie żądanie sieciowe powodujące, że jesteś kod (w przeciwnym razie nie byłoby naprawdę sposobu na obsłużenie więcej niż 1 MB). – Brummo

3

Jak zasugerował Brummo powyżej, jeśli podzielisz go na fragmenty: < 1 MB działa. Oto kod.

public BlobKey putInBlobStoreString(String fileName, String contentType, byte[] filebytes) throws IOException { 
    // Get a file service 
    FileService fileService = FileServiceFactory.getFileService(); 
    AppEngineFile file = fileService.createNewBlobFile(contentType, fileName); 
    // Open a channel to write to it 
    boolean lock = true; 
    FileWriteChannel writeChannel = null; 
    writeChannel = fileService.openWriteChannel(file, lock); 
    // lets buffer the bitch 
    BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(filebytes)); 
    byte[] buffer = new byte[524288]; // 0.5 MB buffers 
    int read; 
    while((read = in.read(buffer)) > 0){ //-1 means EndOfStream 
     ByteBuffer bb = ByteBuffer.wrap(buffer); 
     writeChannel.write(bb); 
    } 
    writeChannel.closeFinally(); 
    return fileService.getBlobKey(file); 
} 
+1

Jest stała dla rozmiaru pobierania maksymalnego blobu w BlobstoreService.MAX_BLOB_FETCH_SIZE = 1015808. Testowałem to w teście lokalnej jednostki i działa zarówno na czytanie, jak i na pisanie. – bigspotteddog

5

Oto jak I odczytu i zapisu dużych plików:

public byte[] readImageData(BlobKey blobKey, long blobSize) { 
    BlobstoreService blobStoreService = BlobstoreServiceFactory 
      .getBlobstoreService(); 
    byte[] allTheBytes = new byte[0]; 
    long amountLeftToRead = blobSize; 
    long startIndex = 0; 
    while (amountLeftToRead > 0) { 
     long amountToReadNow = Math.min(
       BlobstoreService.MAX_BLOB_FETCH_SIZE - 1, amountLeftToRead); 

     byte[] chunkOfBytes = blobStoreService.fetchData(blobKey, 
       startIndex, startIndex + amountToReadNow - 1); 

     allTheBytes = ArrayUtils.addAll(allTheBytes, chunkOfBytes); 

     amountLeftToRead -= amountToReadNow; 
     startIndex += amountToReadNow; 
    } 

    return allTheBytes; 
} 

public BlobKey writeImageData(byte[] bytes) throws IOException { 
    FileService fileService = FileServiceFactory.getFileService(); 

    AppEngineFile file = fileService.createNewBlobFile("image/jpeg"); 
    boolean lock = true; 
    FileWriteChannel writeChannel = fileService 
      .openWriteChannel(file, lock); 

    writeChannel.write(ByteBuffer.wrap(bytes)); 
    writeChannel.closeFinally(); 

    return fileService.getBlobKey(file); 
}