5

Spero che qualcuno possa darmi una mano.Immagine del post HTTP Java di Google App Engine dal metodo API al servlet

Desidero inviare un url come stringa alla funzione endpoint del client, quindi desidero che la funzione endpoint scarichi l'immagine e la invii quindi tramite una richiesta HTTP Post al mio servlet (anch'essa in esecuzione su GAE).

Il problema è - non c'è nessuna immagine pubblicata.

È strano perché se uso lo stesso codice esatto (la classe HttpPost) su un client Android, funziona correttamente: l'immagine viene pubblicata sul servlet e il servlet memorizza l'immagine nel datastore/blobstore.

Non è possibile inviare una richiesta HTTP Post da una funzione endpoint client a un servlet?

Risolto, vedere la risposta qui sotto!


Android:

BackendApi.anyMethod("url-to-any-image").execute(); 

client Endpoint Funzione:

@ApiMethod(path = "anyMethod") 
public void anyMethod(@Named("url") String url) { 
    // -------------------------------------------------- 
    // No input validation here - just a proof of concept 
    // -------------------------------------------------- 

    try { 
    // Download image 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    Resources.asByteSource(new URL(url)).copyTo(buffer); 

    // Upload image 
    HttpPost httpPost = new HttpPost(); 
    httpPost.setTarget(new URL(BlobstoreServiceFactory.getBlobstoreService().createUploadUrl("/upload"))); 
    httpPost.add("image", buffer.toByteArray()); 
    httpPost.send(); 
    } catch (IOException e) { 
    LOG.log(Level.WARNING, e.getMessage(), e); 
    } 
} 

HttpPost Classe:

public class HttpPost { 

    private final static String CRLF = "\r\n"; 

    private String boundary; 

    private URL url; 
    private ByteArrayOutputStream buffer; 

    public HttpPost() { 
    // Generate random boundary 
    // Boundary length: max. 70 characters (not counting the two leading hyphens) 
    byte[] random = new byte[40]; 
    new Random().nextBytes(random); 
    boundary = Base64.encodeBase64String(random); 

    // Init buffer 
    buffer = new ByteArrayOutputStream(); 
    } 

    public void setTarget(URL url) { 
    this.url = url; 
    } 

    public void add(String key, String value) throws IOException { 
    addToBuffer("--" + boundary + CRLF); 
    addToBuffer("Content-Disposition: form-data; name=\"" + key + "\"" + CRLF); 
    addToBuffer("Content-Type: text/plain; charset=UTF-8" + CRLF + CRLF); 
    addToBuffer(value + CRLF); 
    } 

    public void add(String key, byte[] fileBytes) throws IOException { 
    addToBuffer("--" + boundary + CRLF); 
    addToBuffer("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + key + "\"" + CRLF); 
    addToBuffer("Content-Type: application/octet-stream" + CRLF); 
    addToBuffer("Content-Transfer-Encoding: binary" + CRLF + CRLF); 
    addToBuffer(fileBytes); 
    addToBuffer(CRLF); 
    } 

    public void send() throws IOException { 
    // Add boundary end 
    addToBuffer("--" + boundary + "--" + CRLF); 

    // Open url connection 
    HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
    connection.setDoOutput(true); 
    connection.setRequestMethod("POST"); 
    connection.setRequestProperty("Connection", "Keep-Alive"); 
    connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); 
    connection.setRequestProperty("User-Agent", "Google App Engine"); 

    // Open data output stream 
    DataOutputStream request = new DataOutputStream(connection.getOutputStream()); 
    request.write(buffer.toByteArray()); 
    request.flush(); 
    request.close(); 

    // Close connection 
    connection.disconnect(); 
    } 

    private void addToBuffer(String string) throws IOException { 
    buffer.write(string.getBytes()); 
    } 

    private void addToBuffer(byte[] bytes) throws IOException { 
    buffer.write(bytes); 
    } 
} 

Http Servlet:

public class Upload extends HttpServlet { 
    private static final Logger LOG = Logger.getLogger(Upload.class.getName()); 
    private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); 

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { 
    Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request); 

    List<BlobKey> blobKeys = blobs.get("image"); 

    if (blobKeys == null) { 
     LOG.warning("No blobkeys found"); 
     return; 
    } 

    // Get blob key 
    BlobKey blobKey = blobKeys.get(0); 

    if (blobKey == null) { 
     LOG.warning("No blobkey found"); 
     return; 
    } 

    // Create new image object 
    Image image = new Image(); 
    image.setBlobKey(blobKey); 
    image.setTimestamp(new Date()); 

    // Save image to datastore 
    OfyService.ofy().save().entity(image).now(); 

    LOG.log(Level.INFO, "Image upload successful"); 
    } 
} 

risposta

3

conseguenza alla Google App Engine Docs non ti è permesso per andare a prendere il proprio URL:

Per impedire a un'app di causare una ricorsione infinita di richieste, a un gestore di richieste non è consentito recuperare il proprio URL. È ancora possibile causare una ricorsione senza fine con altri mezzi, quindi fai attenzione se la tua app può essere fatta per recuperare richieste di URL fornite dall'utente.

Ciò significa che l'unico modo per fare ciò è scaricare l'immagine sul client Android e quindi postarla su HttpServlet.

Android:

try { 
    // Download image to the Android client 
    ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 
    Resources.asByteSource(new URL(url)).copyTo(buffer); 

    // Upload image to HttpServlet 
    HttpPost httpPost = new HttpPost(); 
    httpPost.setTarget(new URL("http-servlet-upload-url")); 
    httpPost.add("image", buffer.toByteArray()); 
    httpPost.send(); 
    } catch (IOException e) { 
    Logcat.error(e.getMessage()); 
    }