Google App Engine Java HTTP Post 图像从 API 方法到 Servlet
Posted
技术标签:
【中文标题】Google App Engine Java HTTP Post 图像从 API 方法到 Servlet【英文标题】:Google App Engine Java HTTP Post Image from API Method to Servlet 【发布时间】:2015-04-23 01:14:09 【问题描述】:希望有人能帮帮我。
我想将 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");
【问题讨论】:
【参考方案1】:根据Google App Engine Docs,您不能获取自己的 URL:
为防止应用程序导致请求无休止地递归,请求处理程序不得获取其自己的 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());
【讨论】:
以上是关于Google App Engine Java HTTP Post 图像从 API 方法到 Servlet的主要内容,如果未能解决你的问题,请参考以下文章
在 Google App Engine 上解压缩 Java 中的大 blob
Google App Engine (Java) + Spring 管理的 PersistenceManager
在 Google App Engine/Java 中实现通配符搜索
Google-App-Engine 上的 Grails - 它死了吗? [关闭]