使用 jersey-1.7 在 Google Appengine 上上传分段文件
我用 Jersey 在 Google Appengine 上编写了一个应用程序来处理简单的文件上传。这在 jersey 1.2 上运行得很好。在更高版本(当前为 1.7)中,引入了 @FormDataParam 来处理多部分/表单输入。我正在使用 jersey-multipart 和 mimepull 依赖项。似乎新的做法是在 AppEngine 中创建临时文件,我们都知道这是非法的...
因为 Jersey 现在据称与 AppEngine 兼容,所以我是否在这里遗漏了某些内容或做错了什么?
@POST
@Path("upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(@FormDataParam("file") InputStream in) { .... }
当调用这些异常时,上面的方法将会失败......
/upload
java.lang.SecurityException: Unable to create temporary file
at java.io.File.checkAndCreate(File.java:1778)
at java.io.File.createTempFile(File.java:1870)
at java.io.File.createTempFile(File.java:1907)
at org.jvnet.mimepull.MemoryData.createNext(MemoryData.java:87)
at org.jvnet.mimepull.Chunk.createNext(Chunk.java:59)
at org.jvnet.mimepull.DataHead.addBody(DataHead.java:82)
at org.jvnet.mimepull.MIMEPart.addBody(MIMEPart.java:192)
at org.jvnet.mimepull.MIMEMessage.makeProgress(MIMEMessage.java:235)
at org.jvnet.mimepull.MIMEMessage.parseAll(MIMEMessage.java:176)
at org.jvnet.mimepull.MIMEMessage.getAttachments(MIMEMessage.java:101)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readMultiPart(MultiPartReaderClientSide.java:177)
at com.sun.jersey.multipart.impl.MultiPartReaderServerSide.readMultiPart(MultiPartReaderServerSide.java:80)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:139)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:77)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:538)
有人知道吗?有没有办法在阻止 mimepull 创建临时文件的同时做一些事情?
I wrote an application on Google Appengine with Jersey to handle simple file uploading. This works fine when it was on jersey 1.2. In the later versions (current 1.7) @FormDataParam is introduced to handle multipart/form inputs. I am using jersey-multipart and the mimepull dependency. It seems that the new way of doing it is creating temporary files in appengine which we all know is illegal...
Am I missing something or doing something wrong here since Jersey is now supposedly compatible with AppEngine?
@POST
@Path("upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void upload(@FormDataParam("file") InputStream in) { .... }
The above will fail when called with these exceptions...
/upload
java.lang.SecurityException: Unable to create temporary file
at java.io.File.checkAndCreate(File.java:1778)
at java.io.File.createTempFile(File.java:1870)
at java.io.File.createTempFile(File.java:1907)
at org.jvnet.mimepull.MemoryData.createNext(MemoryData.java:87)
at org.jvnet.mimepull.Chunk.createNext(Chunk.java:59)
at org.jvnet.mimepull.DataHead.addBody(DataHead.java:82)
at org.jvnet.mimepull.MIMEPart.addBody(MIMEPart.java:192)
at org.jvnet.mimepull.MIMEMessage.makeProgress(MIMEMessage.java:235)
at org.jvnet.mimepull.MIMEMessage.parseAll(MIMEMessage.java:176)
at org.jvnet.mimepull.MIMEMessage.getAttachments(MIMEMessage.java:101)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readMultiPart(MultiPartReaderClientSide.java:177)
at com.sun.jersey.multipart.impl.MultiPartReaderServerSide.readMultiPart(MultiPartReaderServerSide.java:80)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:139)
at com.sun.jersey.multipart.impl.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:77)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474)
at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:538)
Anyone have a clue? Is there a way to do thing while preventing mimepull from creating the temporary file?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于超出默认大小的文件,
multipart
将创建一个临时文件。为了避免这种情况(在 gae 上创建文件是不可能的),您可以在项目的资源文件夹中创建一个jersey-multipart-config.properties
文件,并向其中添加以下行:然后,代码就是你给了:
For files beyond its default size,
multipart
will create a temporary file. To avoid this — creating a file is impossible on gae — you can create ajersey-multipart-config.properties
file in the project's resources folder and add this line to it:Then, the code is the one you gave:
为了那些在使用 Eclipse 和 GPE(Eclipse 的 Google 插件)时遇到困难的人的利益,我给出了这个从 @yves 的答案中衍生出来的稍微修改的解决方案。
我已使用
App Engine SDK 1.9.10
和Jersey 2.12
对其进行了测试。 它不适用于App Engine SDK 1.9.6 -> 1.9.9 等由于不同的问题。
在您的
\war\WEB-INF\classes
文件夹下创建一个名为jersey-multipart-config 的新文件.properties
。编辑该文件,使其包含行jersey.config.multipart.bufferThreshold = -1
。请注意,
\classes
文件夹在 Eclipse 中是隐藏的,因此请在操作系统的文件资源管理器(例如 Windows 资源管理器)中查找该文件夹。现在,当
multipart
功能初始化时(在 Jersey servlet 初始化时)和文件上传完成时(在 Jersey servlet post 请求时),将不再创建临时文件,GAE 也不会抱怨。For the benefit of those struggling when using Eclipse with GPE (Google Plugin for Eclipse) I give this slightly modified solution derived from @yves' answer.
I have tested it with
App Engine SDK 1.9.10
andJersey 2.12
. It will not work withApp Engine SDK 1.9.6 -> 1.9.9
amongst others due to a different issue.Under your
\war\WEB-INF\classes
folder create a new file calledjersey-multipart-config.properties
. Edit the file so it contains the linejersey.config.multipart.bufferThreshold = -1
.Note that the
\classes
folder is hidden in Eclipse so look for the folder in your operating system's file explorer (e.g. Windows Explorer).Now, both when the
multipart
feature gets initialized (on Jersey servlet initialization) and when a file upload is done (on Jersey servlet post request) the temp file will not be created anymore and GAE won't complain.将文件
jersey-multipart-config.properties
放在 WAR 内的WEB-INF/classes
下非常重要。通常在 WAR 文件结构中,您将配置文件(
web.xml
、appengine-web.xml
)放入WEB-INF/
中,但是这里你需要放入WEB-INF/classes
。Maven 配置示例:
您的项目结构可能如下所示:
jersey-multipart-config.properties 的内容
与 Jersey 2.x:It is very important to put the file
jersey-multipart-config.properties
underWEB-INF/classes
inside the WAR.Usually in a WAR file structure you put the config files (
web.xml
,appengine-web.xml
) intoWEB-INF/
, but here you need to put intoWEB-INF/classes
.Example Maven configuration:
And your project structure can look like:
Content of
jersey-multipart-config.properties
with Jersey 2.x:我找到了以编程方式避免使用临时文件创建的解决方案(对于 GAE 实现非常有用)
我的解决方案包括在我的代码下面创建一个新的 MultiPartReader Provider ...
i've found solution to programmatically avoid to use temporary file creation (very useful for GAE implementation)
My solution consist of creating a new MultiPartReader Provider ... below my code
我们遇到了类似的问题,Jetty 不允许我们上传超过 9194 字节的文件,(突然 - 有一天),我们后来意识到有人从 /tmp(对应于 java.io)获取了我们的用户访问权限。 tmpdir 在某些 Linux 版本上,因此 Jetty 无法将上传的文件存储在那里,我们收到 400 错误。
We experienced a similar problem, Jetty wouldn't let us upload files more than 9194 bytes, (all of a sudden - one day), we realised afterwards that someone had taken our user access from /tmp, which corresponds to java.io.tmpdir on some linux versions, so Jetty couldn't store the uploaded file there, and we got a 400 error.