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

问题描述 投票:5回答:1

我希望有人可以帮助我。

我想将一个url作为字符串发送到客户端端点函数,然后我希望端点函数下载图像并通过HTTP Post请求发送到我的servlet(也在GAE上运行)。

问题是 - 根本没有张贴图片。

这很奇怪,因为如果我在Android客户端上使用完全相同的代码(HttpPost类),它工作正常 - 图像被发布到servlet,servlet将图像存储到数据存储区/ blobstore中。

是否有可能从客户端端点函数向servlet发送HTTP Post请求?

解决了,请看下面的答案!


安卓:

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

客户端端点功能:

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

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");
  }
}
java android google-app-engine servlets google-cloud-datastore
1个回答
3
投票

根据Google App Engine文档,您不能获取自己的网址:

为了防止应用程序导致无休止的请求递归,请求处理程序不允许获取自己的URL。 仍然可以通过其他方式进行无限递归,因此如果您的应用程序可以获取用户提供的URL请求,请务必谨慎。

这意味着这样做的唯一方法是在Android客户端上下载图像,然后将其发布到HttpServlet。

安卓:

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());
  }
© www.soinside.com 2019 - 2024. All rights reserved.