【发布时间】:2014-11-10 10:21:32
【问题描述】:
我正在使用 Jersey 将文件上传到我的应用程序进行处理。我实现了一个可以上传 TXT 和 CSV 文件的版本。但是,当我上传 XLS 文件时,我得到了这个:
Exception in thread "Thread-12" org.jvnet.mimepull.MIMEParsingException: java.io.IOException: Stream Closed
我正在使用 ApachePOI 读取文件,但即使在 xls 方法中,如果我检查流中有多少字节可用,我会得到零。我正在测试的文件肯定有数据,并且是有效的 XLS 文件,但我不明白为什么它认为流已关闭。
我的xls方法如下:
@POST
@NewUpload
@Path(FILE_PATH)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
@AccessLog
public Response xls(
@QueryParam(USER_PARAM) final String userID,
@FormDataParam(FILE_PARAM) final InputStream upload,
@FormDataParam(FILE_PARAM) final FormDataContentDisposition detail,
@FormDataParam(TYPE_PARAM) final String type)
{
try {
System.out.println("Available bytes " + upload.available());
} catch (IOException e) {
System.out.println(ExceptionUtils.getFullStackTrace(e));
}
return upload(userID, upload, detail, type);
} //xls
TXT 和 CSV 的方法完全相同,只是设置为不同的地址,upload(userID, upload, detail, type) 方法适当地处理不同的流。
有没有办法重置流,以便在此之后我可以正确读取它?还是有其他读取 XLS 文件的方法?
对于大文件,是否最好以另一种方式执行此操作,即从上传文件将文件保存到磁盘然后读取它?
提前致谢, 阿列克谢蓝。
编辑 1:
我在 xls 方法中添加了对 IOUtils 的调用以读取一些 Stream 并设法读取了很多字节,所以我猜 Stream 正在被其他东西关闭。
byte [] buffer = new byte[10000];
try {
System.out.println("Bytes read " + IOUtils.read(upload, buffer));
} catch (IOException e) {
System.out.println(ExceptionUtils.getFullStackTrace(e));
}
我将尝试创建一个单元测试来模拟正在发生的事情,这样我就可以看到流被关闭的位置。
编辑 2: 客户端写成前端web应用,用cold fusion写的:
<cfoutput>
<legend>Upload File</legend>
<div id ="uploadfile">
<form class = "form-horizontal" id="upload_file_form" method="post" name="upload_file">
<div class="control-group">
<label class="control-label">File To Upload</label>
<div class="controls">
<input id="filetoupload" class="filetoupload" type="file" name="file">
</div>
</div>
<div class="control-group">
<input type="button"
value="Submit"
name="submit"
class="btn btn-success"
id="submit"
onclick="doUpload(upload_file_form);" />
</div>
</form>
</div>
</cfoutput>
doUpload 脚本:
function doUpload(form) {
var id = $('[name="id"]').val();
var fileExtension = getFileExtension(form);
$.ajax({
type: "POST",
data: new FormData(form),
processData: false,
contentType: false,
url: "/application/rest/upload/" + fileExtension + "/file/?id=" + id,
success:function(data) {
// get the upload id
var uploadID = data;
window.location ="index.cfm?controller=project&action=status&id=" + id + "&uploadID='" + uploadID + "'";
}
});
}
目前我正在组件测试中运行上传,这让我意识到文件的标题已被读取,但是组件测试中的文件类型为BufferedInputStream,但从客户端运行代码时的流是org.jvnet.mimepull.DataHead$ReadMultiStream 所以这可能是 mimepull 依赖的问题,有什么想法吗?
干杯, 阿列克谢蓝。
编辑 3:我想我找到了问题所在。在我的上传方法中,我在另一个线程中关闭了进程,以确保请求不会等待。 Jersey 必须在从方法返回时关闭流,并且 CSV 和 TXT 是非常简单的文件类型,它们必须在开始线程返回之前在线程中处理。我明天需要确认这一点,因为我今天没时间了,但我一定会发布结果。上传方式如下:
protected Response upload(
final String id,
final InputStream input,
final FormDataContentDisposition detail,
final String type)
{
String id = UUIDs.timeBased().toString();
factory
.set(id, uploadID)
.setFilename(detail.getFileName())
.setType(type);
new Thread(new Runnable()
{
@Override
public void run()
{
upload.process(input);
} //run
}).start();
return Response.ok(uploadID).build();
} //upload
【问题讨论】:
-
您可以从上传文件的位置添加客户端部分吗?
-
嗨@tmarwen 请参阅编辑 2 了解前端客户端和更多详细信息。我将尝试在 mimepull 库中找到 DataHead 的代码,看看发生了什么。
标签: java rest upload jersey xls