2011-04-02 7 views
7

Estoy usando App Engine (version 1.4.3) direct write the blobstore para guardar imágenes. cuando trato de guardar una imagen que es mayor que 1 MB me sale el siguiente ExcepciónLímite de cuota de 1 MB para un objeto blobstore en Google App Engine?

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

pensé que el limit for each object is 2GB

Este es el código Java que almacena la imagen

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

se parece a dividir los datos en partes más pequeñas hizo el truco. Aún recibí la excepción cuando traté de almacenar un gran registro de DataStore (que tiene un límite de 1MB). dado que el seguimiento de la pila de excepción estaba en un hilo diferente, pensé que era el blobStore el que causaba los problemas. Google: me debes varias horas de depuración –

+0

Si hubieras incluido la stacktrace (o la hubieras examinado de cerca), podríamos haber ayudado. –

+0

* ACTUALIZACIÓN * el código anterior parece funcionar para mí. Parece que ya no hay un límite de 1 mb ... – itgiawa

Respuesta

3

El tamaño máximo del objeto es de 2 GB, pero cada llamada API solo puede manejar un máximo de 1 MB. Al menos para leer, pero supongo que puede ser lo mismo para escribir. Por lo tanto, puede tratar de dividir la escritura del objeto en trozos de 1 MB y ver si eso ayuda.

+0

Traté de dividir la escritura en varias invocaciones writeChannel.write, pero obtuve los mismos resultados –

+0

¿Qué significa que "cada llamada API solo puede manejar un máximo de 1 MB"? cual API? ¿significa 1MB por solicitud (mi aplicación)? –

+0

No, supongo que significa más o menos cada función llamada, no la solicitud web que desencadena su código (de lo contrario, realmente no habría manera de manejar más de 1 MB). – Brummo

3

Como Brummo sugirió anteriormente si lo dividió en trozos < 1MB funciona. Aquí hay un código.

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

Hay una constante para el tamaño máximo de captación de blobs en BlobstoreService.MAX_BLOB_FETCH_SIZE = 1015808. Probé esto en una prueba de unidad local y funciona tanto para lectura como para escritura. – bigspotteddog

5

Aquí es cómo leer y escribir archivos de gran tamaño:

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); 
}