我已经尝试了几个小时,所以也许新的眼光会有所帮助。
我正在尝试使用 Google App Engine 上的 GWT(使用 UiBinder)将文件上传到服务器。按照我能找到的所有示例,事情看起来应该可以工作,但服务器的“post”方法显示已上传 0 个项目。
这是客户端代码:
FormUploader.ui.xml:
<g:FormPanel action="/formImageUploader" ui:field="formPanel">
<g:VerticalPanel>
<g:FileUpload ui:field="uploader"></g:FileUpload>
<g:Button ui:field="submit">Submit</g:Button>
</g:VerticalPanel>
</g:FormPanel>
FormUploader.java:
@UiField
FormPanel formPanel;
@UiField
FileUpload uploader;
@UiField
Button submit;
public FormUploader() {
initWidget(uiBinder.createAndBindUi(this));
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
formPanel.setMethod(FormPanel.METHOD_POST);
addSubmitHandlers();
}
private void addSubmitHandlers() {
formPanel.addSubmitCompleteHandler(new SubmitCompleteHandler() {
@Override
public void onSubmitComplete(SubmitCompleteEvent event) {
Core.log("Inside submitComplete");
Window.alert(event.getResults());
}
});
}
web.xml:
<servlet>
<servlet-name>formImageUploader</servlet-name>
<servlet-class>com.company.server.FormImageUploader</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>formImageUploader</servlet-name>
<url-pattern>/formImageUploader</url-pattern>
</servlet-mapping>
FormImageUploader.java:
public class FormImageUploader extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
log.info("Request.getContentLength(): " + request.getContentLength());
log.info("Content type: " + request.getContentType());
log.info("Parm names: ");
for (Object paramName : request.getParameterMap().keySet()) {
log.info("__Param name: " + paramName.toString());
}
log.info("Attribtue names: ");
Enumeration enu = request.getAttributeNames();
while (enu.hasMoreElements()) {
log.info("__Attribute name: " + enu.nextElement().toString());
}
log.info("Header names: ");
enu = request.getHeaderNames();
while (enu.hasMoreElements()) {
log.info("__Header name: " + enu.nextElement().toString());
}
resp.getWriter().println("Post Code has finished executing");
}
所有这些都执行得很好,客户端显示一个包含邮政代码已完成执行的警告框,但我不知道如何获取我要上传的文件的内容。
这是服务器端日志:
Request.getContentLength(): 63
Content type: multipart/form-data; boundary=---------------------------194272772210834546661
Parm names:
Attribtue names:
__Attribute name: com.google.apphosting.runtime.jetty.APP_VERSION_REQUEST_ATTR
任何人都可以帮我看看为什么我在客户端上单击“提交”后在服务器上看不到任何文件吗?
提前致谢
编辑:
仍然不明白为什么我无法在服务器上获取表单数据。我正在关注this example ,并且只是尝试将响应写入客户端,但服务器肯定看不到来自客户端的任何内容。
服务器代码:
try {
log.info("Inside try block");
ServletFileUpload upload = new ServletFileUpload();
log.info("created the servlet file upload");
res.setContentType("text/plain");
log.info("set the content type to text/plain");
FileItemIterator iterator = upload.getItemIterator(req);
log.info("Got the iterator for items");
while (iterator.hasNext()) {
log.info("__inside iterator.hasNext");
FileItemStream item = iterator.next();
log.info("__assigned the file item stream");
InputStream stream = item.openStream();
log.info("__opened said stream");
if (item.isFormField()) {
log.warning("Got a form field: " + item.getFieldName());
} else {
log.warning("Got an uploaded file: " + item.getFieldName() +
", name = " + item.getName());
int len;
byte[] buffer = new byte[8192];
while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
res.getOutputStream().write(buffer, 0, len);
}
log.info("Done writing the input to the output stream");
}
}
} catch (Exception ex) {
log.severe("Exception; " + ex);
throw new ServletException(ex);
}
log.info("Done parseInput3");
日志:
Inside parseInput3
Inside try block
created the servlet file upload
set the content type to text/plain
Got the iterator for items
Done parseInput3
同样,它绝对无法迭代服务器上的文件项...知道为什么吗?
最佳答案
事实证明,GAE 有一种完全不同的上传文件(Blob)的方式: http://code.google.com/appengine/docs/java/blobstore/overview.html#Uploading_a_Blob
您需要向客户端上的表单提供来自服务器的 Blobstore 上传 URL(超时),可使用以下方式检索:
blobstoreService.createUploadUrl('urlToRedirectToAfterUploadComplete')
在表单操作上设置上传 URL 后,表单将被提交,并且 Blobstore 服务将重定向到提供的 URL,然后该 URL 可以访问 Google 存储的对象的 BlobKey
。
因此,我将以下 ChangeHandler
添加到我的 GWT FileUpload
中:
private void addChangeListener() {
Core.log("Selected file: " + uploader.getFilename());
uploader.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
MyApp.SERVICES.getUploadUrl(new SuccessAsyncCallback<String>() {
@Override
public void onSuccess(String uploadUrl) {
form.setAction(uploadUrl);
form.submit();
Core.log("Submitted form with upload url: " + uploadUrl);
}
});
}
});
}
然后在 servlet 中,我在上传后将 GAE 重定向到:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws Exception {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
// where 'uploader' is the name of the FileUploader (<input type='file'>) control on the client
List<BlobKey> blobKeys = blobs.get("uploader");
resp.getOutputStream().print(blobKeys.get(0).getKeyString());
}
注意!
如果 FileUpload
控件没有定义 name="whateveryouwantthenametobe"
属性,则在尝试获取上传的 blob 值时,GAE 将引发 OutOfMemory 异常,即使你告诉它(使用 UiBinder)id 是 ui:field="nameofControl"
关于google-app-engine - 如何使用GWT在GAE上上传文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9812403/