关键词:
【中文标题】使用 Java 上传文件(带进度条)【英文标题】:File Upload with Java (with progress bar) 【发布时间】:2010-09-20 06:17:55 【问题描述】:我对 Java 非常陌生,而且我主要是边学边自学,所以我开始构建一个小程序。我想做一个可以从本地磁盘中选择文件并将其作为多部分/表单数据 POST 请求上传但带有进度条的文件。显然,用户必须授予 Java 小程序访问硬盘的权限。现在我已经完成了第一部分的工作:用户可以使用JFileChooser
对象选择一个文件,该对象可以方便地返回一个File
对象。但我想知道接下来会发生什么。我知道File.length()
会给我文件的总大小(以字节为单位),但是如何将选定的File
发送到网络,以及如何监控已发送的字节数?提前致谢。
【问题讨论】:
这只是一个旁注,我讨厌公司使用小程序来提供更好的上传界面和 html 中的界面。我觉得这是一个网络浏览器问题。您不能盲目相信请求许可的小程序,但大多数用户还是会给予许可。悲伤但真实。 @Pyrolistical 我同意,但不幸的是,浏览器对上传文件的支持仍然很糟糕。如果您需要/希望对这些文件进行任何客户端处理,除了使用小程序或闪存之外,您别无选择。 【参考方案1】:侦听器返回的字节数与原始文件大小不同。因此,我没有使用transferred++
,而是将其修改为transferred=len
;这是写入输出流的实际字节数的长度。当我计算传输的总字节数之和时,它等于CountingMultiPartEntity.this.getContentLength();
返回的实际ContentLength
public void write(byte[] b, int off, int len) throws IOException
wrappedOutputStream_.write(b,off,len);
transferred=len;
listener_.transferred(transferred);
【讨论】:
【参考方案2】:如果不想创建类,您可以从其他答案中重写 AbstractHttpEntity
子类或实现 public void writeTo(OutputStream outstream)
方法。
使用FileEntity
实例的示例:
FileEntity fileEntity = new FileEntity(new File("img.jpg"))
@Override
public void writeTo(OutputStream outstream) throws IOException
super.writeTo(new BufferedOutputStream(outstream)
int writedBytes = 0;
@Override
public synchronized void write(byte[] b, int off, int len) throws IOException
super.write(b, off, len);
writedBytes+=len;
System.out.println("wrote: "+writedBytes+"/"+getContentLength()); //Or anything you want [using other threads]
);
;
【讨论】:
【参考方案3】:更简单的countingEntity 不会依赖于特定的实体类型,而是扩展HttpEntityWrapped
:
package gr.phaistos.android.util;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.HttpEntity;
import org.apache.http.entity.HttpEntityWrapper;
public class CountingHttpEntity extends HttpEntityWrapper
public static interface ProgressListener
void transferred(long transferedBytes);
static class CountingOutputStream extends FilterOutputStream
private final ProgressListener listener;
private long transferred;
CountingOutputStream(final OutputStream out, final ProgressListener listener)
super(out);
this.listener = listener;
this.transferred = 0;
@Override
public void write(final byte[] b, final int off, final int len) throws IOException
//// NO, double-counting, as super.write(byte[], int, int) delegates to write(int).
//super.write(b, off, len);
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
@Override
public void write(final int b) throws IOException
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
private final ProgressListener listener;
public CountingHttpEntity(final HttpEntity entity, final ProgressListener listener)
super(entity);
this.listener = listener;
@Override
public void writeTo(final OutputStream out) throws IOException
this.wrappedEntity.writeTo(out instanceof CountingOutputStream? out: new CountingOutputStream(out, this.listener));
【讨论】:
我将如何实现这个?如果你回答可以标记我吗:) 喜欢这个 ProgressListener listener = new ProgressListener() @Override public void transfer(long num) parentTask.publicPublishProgress(num); ; StringEntity se = new StringEntity(XML); CountingHttpEntity ce = new CountingHttpEntity(se, listener); httppost.setEntity(ce);【参考方案4】:要使用 HttpClient 检查进度,请将 MultipartRequestEntity 包裹在一个计算发送字节数的地方。包装如下:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.httpclient.methods.RequestEntity;
public class CountingMultipartRequestEntity implements RequestEntity
private final RequestEntity delegate;
private final ProgressListener listener;
public CountingMultipartRequestEntity(final RequestEntity entity,
final ProgressListener listener)
super();
this.delegate = entity;
this.listener = listener;
public long getContentLength()
return this.delegate.getContentLength();
public String getContentType()
return this.delegate.getContentType();
public boolean isRepeatable()
return this.delegate.isRepeatable();
public void writeRequest(final OutputStream out) throws IOException
this.delegate.writeRequest(new CountingOutputStream(out, this.listener));
public static interface ProgressListener
void transferred(long num);
public static class CountingOutputStream extends FilterOutputStream
private final ProgressListener listener;
private long transferred;
public CountingOutputStream(final OutputStream out,
final ProgressListener listener)
super(out);
this.listener = listener;
this.transferred = 0;
public void write(byte[] b, int off, int len) throws IOException
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
public void write(int b) throws IOException
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
然后实现一个更新进度条的 ProgressListener。 请记住,进度条更新不能在 Event Dispatch Thread 上运行。
【讨论】:
为什么 CountingMultipartRequestEntity 应该包裹在 MultipartRequestEntity 周围? 各位,你的答案不正确。在许多情况下,这将重复计算所有发送的字节。 FilterOutputStream#write(byte[],int,int) 只是在循环中调用 FOS.write(byte) ,因此您对所有字节进行了重复计算。此外,FOS 文档建议更改此行为,因为它效率不高。请参阅我的答案,我在其中保存基础流并将其称为 write(byte[],int,int) 方法。 @Harny 我回答了这个问题,我也修复了这个答案以做正确的事情。 如果有人遇到同样的问题,您要使用此特定示例的 .jar 是 commons-httpclient-3.0.1 ,它作为存档副本存储在 Apache HttpClient 项目页面上。较新的版本似乎没有此示例使用的界面。 很棒的答案。如果您正在寻找上述代码的调用方,我发现本教程可以帮助我理解双方。 toolongdidntread.com/android/…【参考方案5】:只是我的 2c 价值:
这是基于 tuler 的回答(在撰写本文时有一个错误)。我稍微修改了一下,所以这是我的 tuler 和 mmyers 答案版本(我似乎无法编辑他们的答案)。我想尝试使它更清洁和更快。除了错误(我在 cmets 中讨论他们的答案)之外,我对他们的版本的一个大问题是它会在每次写入时创建一个新的 CountingOutputStream
。这在内存方面可能会变得非常昂贵 - 大量的分配和垃圾收集。较小的问题是当它可以扩展 MultipartEntity
时使用委托。不知道他们为什么选择那个,所以我以我更熟悉的方式做了。如果有人知道这两种方法的优缺点,那就太好了。最后,FilterOutputStream#write(byte[], int,int) 方法只是在循环中调用FilterOutputStream#write(byte)。 FOS documentation 建议子类覆盖此行为并使其更有效。最好的方法是让底层的 OutputStream 处理写入请求。
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CountingMultiPartEntity extends MultipartEntity
private UploadProgressListener listener_;
private CountingOutputStream outputStream_;
private OutputStream lastOutputStream_;
// the parameter is the same as the ProgressListener class in tuler's answer
public CountingMultiPartEntity(UploadProgressListener listener)
super(HttpMultipartMode.BROWSER_COMPATIBLE);
listener_ = listener;
@Override
public void writeTo(OutputStream out) throws IOException
// If we have yet to create the CountingOutputStream, or the
// OutputStream being passed in is different from the OutputStream used
// to create the current CountingOutputStream
if ((lastOutputStream_ == null) || (lastOutputStream_ != out))
lastOutputStream_ = out;
outputStream_ = new CountingOutputStream(out);
super.writeTo(outputStream_);
private class CountingOutputStream extends FilterOutputStream
private long transferred = 0;
private OutputStream wrappedOutputStream_;
public CountingOutputStream(final OutputStream out)
super(out);
wrappedOutputStream_ = out;
public void write(byte[] b, int off, int len) throws IOException
wrappedOutputStream_.write(b,off,len);
++transferred;
listener_.transferred(transferred);
public void write(int b) throws IOException
super.write(b);
【讨论】:
这比另一个小问题要多得多。【参考方案6】:我最终偶然发现了一个开源 Java 上传器小程序,并在其代码中找到了我需要知道的一切。以下是描述它的博客文章的链接以及来源:
ArticleSource Code
【讨论】:
源代码链接已失效。 不足为奇,因为我的问题是 12 岁。从那时起,情况发生了巨大变化,所以如果我是你,我绝对不会在 2020 年使用 Java 小程序来处理文件上传。首先,我认为这些现在通常被主流浏览器阻止,其次,我当时所追求的功能现在在 HTML5 中得到了完全支持。根本不需要涉及Java。 2008 年的必要做法是今天的糟糕做法。 我不是这个意思,哈哈。这只是对使用没有 S.O. 内容的链接的评论。因为死链接,但我没有在第一条评论中说清楚。但实际上我正在研究上传反馈的方法,而不是使用某种 gui,如 applet、swing、javafx 甚至 HTML。问候!【参考方案7】:Apache common 是一个很好的选择。 Apache common 允许您配置以下内容。
-
配置(xml文件)最大文件大小/上传文件大小
目标路径(上传文件的保存位置)
设置温度。文件夹来交换文件,这样文件上传会很快。
【讨论】:
Apache Commons 组件中的哪一个?【参考方案8】:请记住,当网络中的中间组件(例如,ISP 的 HTTP 代理或服务器前的反向 HTTP 代理)比服务器更快地消耗您的上传时,进度条可能会产生误导。
【讨论】:
【参考方案9】:正如文森特发布的文章所述,您可以使用 Apache commons 来执行此操作。
小碎碎念
DiskFileUpload upload = new DiskFileUpload();
upload.setHeaderEncoding(ConsoleConstants.UTF8_ENCODING);
upload.setSizeMax(1000000);
upload.setSizeThreshold(1000000);
Iterator it = upload.parseRequest((HttpServletRequest) request).iterator();
FileItem item;
while(it.hasNext())
item = (FileItem) it.next();
if (item.getFieldName("UPLOAD FIELD")
String fileName = item.getString(ConsoleConstants.UTF8_ENCODING);
byte[] fileBytes = item.get();
【讨论】:
【参考方案10】:查看HTTP Client 以将文件上传到网络。它应该能够做到这一点。我不确定如何获取进度条,但它会涉及以某种方式查询该 API。
【讨论】:
jqueryajax实现上传文件代码,带进度条
原文:jqueryajax实现上传文件代码,带进度条 源代码下载地址:http://www.zuidaima.com/share/1550463291116544.htmajax上传文件代码,带进度条的。首页http://localhost:端口/项目名/common/test.htm上传中标签: jquery ajax 上传 ... 查看详情
jqueryajax实现上传文件代码,带进度条
原文:jqueryajax实现上传文件代码,带进度条 源代码下载地址:http://www.zuidaima.com/share/1550463291116544.htmajax上传文件代码,带进度条的。首页http://localhost:端口/项目名/common/test.htm上传中标签: jquery ajax 上传 查看详情
java多文件上传显示进度条
...进度。手上有类似代码的朋友联系我,扣-15080818,跪求!使用 apachefileupload ,springMVC jquery1.6x,bootstrap 实现一个带进度条的多文件上传,由于fileupload的局限,暂不能实现每个上传文件都显示进度条,只能实现一个总的进度... 查看详情
springmvc带进度条的多文件上传
1、关于文件上传进度条的实现在说SpringMVC文件上传尤其是带滚动条之前先用servlet做一个简单的文件上传并返回进度信息这样的功能。(1)需要两个包:commons-fileupload-1.3.1.jarcommons-io-1.4.jar上面这两个包是Apache推出的... 查看详情
[layui]上传文件带进度条+表单提交功能优化(代码片段)
上传文件带进度条+表单提交功能优化前期做了一个简视频提交;每次只提交一个需要重新上传。视频文件较大时候没有进度提示,用户体验并不好,今天做一个简单的优化!如果监听提交表单时候,回调路径可能还未完成。提... 查看详情
asp.net上传大文件带进度条swfupload
Asp.Net基于swfupload上传大文件带进度条百分比显示,漂亮大气上档次,大文件无压力,先看效果一、上传效果图1、上传前界面:图片不喜欢可以自己换2、上传中界面:百分比显示 3、上传后返回文件地址,我测试呢所以乱写... 查看详情
html5jquery+formdata异步上传文件,带进度条
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link href=". 查看详情
webuploader插件单个文件上传(带进度条)
@{ViewBag.Title="主页";}<scriptsrc="~/Scripts/jquery-1.9.1.min.js"></script><linkhref="~/Scripts/1/bootstrap.css"rel="stylesheet"/><linkhref="~/Scripts/1/webuploader.css"rel="styles 查看详情
ajax大文件切割上传以及带进度条。
分块传输的原理就是利用HTML5新增的文件slice截取函数。 代码如下:html:<inputid="f"type="file"name="part"onchange="writeFile()">JS:核心部分已经加粗显示了,其他部分不用看,因为实现的方式有很多种,不一定要按照我的方式去... 查看详情
使用 RestTemplate.postForLocation 的文件上传进度条
】使用RestTemplate.postForLocation的文件上传进度条【英文标题】:FileuploadprogressbarusingRestTemplate.postForLocation【发布时间】:2012-12-0217:15:29【问题描述】:我有一个将文件上传到REST服务的Java桌面客户端应用程序。所有对REST服务的调... 查看详情
利用formdata对象+xhr新特性实现文件上传——带进度条(代码片段)
小编今天又get到一个新技能,就是上传图片并显示进度条,话不多说,直接进入正题!冲冲冲!!💪实现效果:当点击上传文件按钮后,如果未选择文件,会跳出请选择要上传的文件提示框... 查看详情
使用 jQuery 的文件上传进度条
】使用jQuery的文件上传进度条【英文标题】:FileuploadprogressbarwithjQuery【发布时间】:2013-03-0220:39:19【问题描述】:我正在尝试在我的项目中实现AJAX文件上传功能。我为此使用jQuery;我的代码使用AJAX提交数据。我还想实现一个文... 查看详情
使用 jQuery 的文件上传进度条
】使用jQuery的文件上传进度条【英文标题】:FileuploadprogressbarwithjQuery【发布时间】:2013-03-0220:39:19【问题描述】:我正在尝试在我的项目中实现AJAX文件上传功能。我为此使用jQuery;我的代码使用AJAX提交数据。我还想实现一个文... 查看详情
使用 jquery ui 进度条上传文件
】使用jqueryui进度条上传文件【英文标题】:fileuploadwithjqueryuiprogressbar【发布时间】:2011-01-2015:13:55【问题描述】:我正在使用jCrop,我想为图片上传添加一个进度条,如何让jqueryui进度条加载图片字节?【问题讨论】:我相信这... 查看详情
如何使用进度条快速上传大文件?
】如何使用进度条快速上传大文件?【英文标题】:Howtouploadlargefileinexpresswithprogressbar?【发布时间】:2012-10-1201:46:31【问题描述】:目前我正在使用socket.io上传带有进度条的视频。这是教程http://net.tutsplus.com/tutorials/javascript-ajax/h... 查看详情
php使用进度条上传文件(代码片段)
文件上传和进度条
...在上传文件时根据读取的文件数量显示进度条。我们如何使用JS和Servlet来实现这一点我知道上传我可以使用apachecommonslib,但如何根据读取的数据显示进度条。我是否应该根据读取的数据量向JS代码发送计数响应,如果可以,如何... 查看详情
使用 XMLHttpRequest 上传大文件时的进度条
】使用XMLHttpRequest上传大文件时的进度条【英文标题】:ProgressbarwhileuploadinglargefileswithXMLHttpRequest【发布时间】:2013-04-0415:27:08【问题描述】:我正在尝试使用XMLHttpRequest和file.slice将一些大文件上传到服务器。我已经在文档和其... 查看详情