简体   繁体   English

从API方法到Servlet的Google App Engine Java HTTP Post Image

[英]Google App Engine Java HTTP Post Image from API Method to Servlet

I hope someone can help me out. 我希望有人可以帮助我。

I want to send a url as a string to the client endpoint function and then I want the endpoint function to download the image and send it then via a HTTP Post request to my servlet (also running on GAE). 我想将一个url作为字符串发送到客户端端点函数,然后我希望端点函数下载图像并通过HTTP Post请求发送到我的servlet(也在GAE上运行)。

The problem is - there is no image posted at all. 问题是 - 根本没有张贴图片。

It's strange because if I use the exact same code (the HttpPost class) on an android client, it works fine - the image gets posted to the servlet and the servlet stores the image into the datastore / blobstore. 这很奇怪,因为如果我在Android客户端上使用完全相同的代码(HttpPost类),它工作正常 - 图像被发布到servlet,servlet将图像存储到数据存储区/ blobstore中。

Isn't it possible to send a HTTP Post request from a client endpoint function to a servlet? 是否有可能从客户端端点函数向servlet发送HTTP Post请求?

Solved, see answer below! 解决了,请看下面的答案!


Android: 安卓:

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

Client Endpoint Function: 客户端端点功能:

@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 Class: HttpPost类:

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

Accordingly to the Google App Engine Docs you are not allowed to fetch your own URL: 根据Google App Engine文档,您不能获取自己的网址:

To prevent an app from causing an endless recursion of requests, a request handler is not allowed to fetch its own URL. 为了防止应用程序导致无休止的请求递归,请求处理程序不允许获取自己的URL。 It is still possible to cause an endless recursion with other means, so exercise caution if your app can be made to fetch requests for URLs supplied by the user. 仍然可以通过其他方式进行无限递归,因此如果您的应用程序可以获取用户提供的URL请求,请务必谨慎。

That means the only way of doing this is to download the image on the Android client and then post it to the HttpServlet. 这意味着这样做的唯一方法是在Android客户端上下载图像,然后将其发布到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());
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM