springmvc实现上传文件进度条数值显示错乱
最近做了一个文件上传进度条显示的功能,框架是基于springmvc的。
    参考:http://my.oschina.net/xiaotian120/blog/198225  做的
    ![图片说明](https://img-ask.csdn.net/upload/201606/21/1466478269_320000.png)
        ps:目前这边是服务端计算了上传进度之后,存入到session中,页面定时取这个session中的值,从而进行进度条展示的。  因为进度条的数值是存到session中的,那么

这样做的话,有两个问题,不知道怎么解决

    问题一(急!!!):
       同一个浏览器的不同标签页进行文件上传,那么上传文件的进度条数值会乱串,不知道该怎么解决。


    问题二:
         同一个浏览器的同一个标签页有两个上传文件的按钮,两个文件同时上传文件,那么上传的进度条数值会相互串,不知道有什么好的解决方式?(目前我就简单的js控制,让用户一次只能上传一个文件)

3个回答

假设上传的时候附带的文本信息中拥有key如: uploadKey;
首先有个个上传下载的全局维护map
如:
private final static ConcurrentHashMap<Long, String> uploadKeys = new ConcurrentHashMap<Long, String>();
提供下载的key的放入和提取方法:
public static void putKey(uploadKey) {
uploadKeys.put(Thread.currentThread().getId(), uploadKey);
}

public static void getKey(){
uploadKeys.get(Thread.currentThread().getId());
}

public static void removeKey(){
uploadKeys.remove(Thread.currentThread().getId());
}
当有下载请求过来的时候:
首先获取文本中的uploadKey,然后调用管理key的putKey方法,
在上传过程中,也就是在你的FileUploadProgressListener中,方法session进度时getKey就可以。
最后上传完成,准备响应的时候removeKey.

这个思路应该够了吧,如果有帮助,希望采纳

w172087242
little_how 回复乐开享001: 这边读取完成,只能代表客户端发送的字节你读取完成了,剩下的就是磁盘操作,如果逻辑不复杂,本地io没有竞争的情况下,很快的,你可以把进度条设置到99%,具体看你的业务
接近 4 年之前 回复
gooooooal
乐开享001 监听器这边的是读取文件的比特数(会不会是一边读取,一边上传,当读取完成之后,实际上真正文件还没有上传完成??),和真正的上传时候,是不是有差异,如果有,请问你有什么好的解决方式吗? /** * pBytesRead 到目前为止读取文件的比特数 pContentLength 文件总大小 pItems 目前正在读取第几个文件 */ public void update(long pBytesRead, long pContentLength, int pItems)
接近 4 年之前 回复
gooooooal
乐开享001 不好意思,是我代码上的问题,用你说的方式解决了上传进度条数值的问题了,非常感谢。但是我做测试的时候发现,在同一个浏览器的同一个标签页,如果同时上传比较大的文件(第一个文件上传了50%在上传第二个文件),那么当进度条的数据到了100%,上传文件的ajax还没有返回,都到了100%之后,要等6S左右才弹出上传成功。不知道是什么原因
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 权限问题,是不是共享了跨域资源了?
接近 4 年之前 回复
gooooooal
乐开享001 配置文件也改成多例的了,也是不行的: <bean id="multipartResolver" scope="prototype" class="com.sunsharing.ihome.air.web.common.fileupload.CustomMultipartResolver">
接近 4 年之前 回复
gooooooal
乐开享001 遇到最新问题,一个浏览器两个标签页,同时上传,遇到问题:securityError:Blocked a frame with origin "" from accessing a cross-origin frame 详细图片地址:![图片说明](http://img.ask.csdn.net/upload/201606/22/1466589151_365204.png)
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 你那里设置有问题吧,上传就是http的解析过程,你都知道是做上传操作了,代表springmvc已经对http的报文头进行了解析
接近 4 年之前 回复
gooooooal
乐开享001 点击上传按钮之后,是先到监听器这边,那么在监听器这边取不到值的
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 分别在putKey那里输出线程id和key值,在getKey那里输出线程id和key值,对比对比
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 确定吗?你可以log日志输出一下看看,而且这样的管理不如ession.setAttribute("upload_ps", Map<GlobalThreadMap.getKey(),status>)(语法不要计较,就是想表达map结构)这样的管理才是最好的
接近 4 年之前 回复
gooooooal
乐开享001 在监听器这边 调用 uploadKeys.get(Thread.currentThread().getId()); 这个,是取不到值的
接近 4 年之前 回复
gooooooal
乐开享001 在监听器部分: //session.setAttribute("upload_ps", status); //这是之前的将进度条的数值设置到session里面 session.setAttribute(GlobalThreadMap.getKey(), status);//这是现在的 但是key去取出来是一个空的值,我是在上传文件开始的地方设置的值
接近 4 年之前 回复
gooooooal
乐开享001 刚刚我试了以下,感觉还是有问题的
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 再对一个线程处理两个上传的再进行处理啊,一个线程处理两个上传,如果在程序设置那里没有用异步,那么,肯定是一个文件写完,再写另外一个文件的,http的流都是顺序传输的。
接近 4 年之前 回复
gooooooal
乐开享001 如果两个文件同时上传呢,那么所维护的这个静态map的key 不就被覆盖了吗
接近 4 年之前 回复

在提交的时候,对上传任务进行编号,js端以时间戳加随机数编号就可以,把编号值传入服务端。
在服务端session中对上传进度和编号进行一对一放入。
获取的时候对比编号找出自己的那个上传任务,然后展示进度条就ok了。

如果有帮助,希望采纳

gooooooal
乐开享001 我还是不知道怎么弄,那个你有时间没有,方便做个简单的demo吗,谢谢了啊,真不会弄的
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: 方式是很多的,在多线程环境下就考虑用线程相关的操作来做,这样就会慢慢出现思路的
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: Thread.currentThread().getId(),也可以直接用ThreadLocal来管理前端传过来的那串标识
接近 4 年之前 回复
w172087242
little_how 回复乐开享001: FileUploadProgressListener里面是可以获取当前线程id的,前端传递过来的值首先与线程id对应,因为处理一个上传请求的是不同的线程。
接近 4 年之前 回复
gooooooal
乐开享001 你提出来的这个我也想过,可是,如何向 这个扩展的监听器里面传值进去呢,FileUploadProgressListener implements ProgressListener
接近 4 年之前 回复

图片说明

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问