① 写给产品经理之前端是如何展示后端数据的
移动互联网的迅猛发展让移动APP呈现出爆发之势,这两年更是移动开发程序员的春天。
今天的互联网上充斥着产品与技术的撕逼。也许你会问产品经理到底要不要懂技术?由此引申出,产品经理到底要不要懂设计?产品经理到底要不要懂运营?产品经理到底要不要懂市场?产品经理到底要不要懂业务?这所有问题的来源都是大家对于产品经理的工作认识不一致。
每个人心中都有一个产品经理的定义,产品经理在技术方面更多的是去统筹和规划。不是画画图写写文档就可以了。这里面更多的需要的是对逻辑的梳理和拆分。
例如很简单的一个app内嵌发红包的活动,产品经理需要确定整个活动的流程。从用户进入页面的那一瞬间就应该被产品经理掌控。他的每一个步骤,每一个操作会带来什么结果,有哪些变量会导致活动进程失败,这些都要产品去考虑。等到活动逻辑和过程全部梳理完成,下面就要进行拆分了。还是以发红包为例,红包中金额是客户端写死还是服务端进行计算,红包领取资格需要服务端返回几种结果,每种结果对应客户端的提示是什么,用户领取红包以后服务端需要记录那些信息(帐号,uid,领取时间,金额,是否使用等),客户端哪些地方需要加入计数器进行数据统计。总结起来其实就是,产品经理需要根据开发的每一个环节,将所有内容分类整理,并分发给不同部分的开发进行研发。最后,还需要给测试准备好check list,当测试按照check list测试完成以后,才可以上线。
以上种种都需要产品对前端如何显示后端数据有一个清晰的认识才能规划好数据如何展示。是APP写死呢还是后台返回,在用户任务进行的时候有哪些可能case。只有搞清楚这些,产品才能在实际的开发中掌握好整个项目的流程与进展,才能不被开发给糊弄。
简单的说,前端仅仅将后端返回的数据展示在页面上,不做过多的逻辑处理。前端需要关心的是,数据如何更好的展示出来,页面效果如何做出来,以及其性能问题。
而后端就是负责对这些数据进行处理,提供给前端展示。
前端一般有H5、android、ios等多端界面。数据不要轻易写死在前端里面,不然到时候三端都要修改,费时费力。而将这些变化多数据让后端进行处理,前端将这个数据取出来显示出来就行了。
举个例子吧,下图是一个美团app首页团购的展示效果
上方美食等8个icon一般为固定展示栏目,非特殊情况不会修改。那么前端一般是写死在app中,等到需要更新的时候更新app即可。
而下方猜你喜欢是一个列表,该列表数据经常变化,数据写在服务端维护,app取出数据进行展示即可。
首先,前段对页面的展示是分两步走的。
第一、在本地绘制好界面,当然此时未连api会填充一些假数据,或写一些默认值。
第二、连api进行数据获取,将数据填充进界面。
既然如此,咱们简单看下前端拿到的数据到底长什么样的吧。
现在前端获取到的数据基本是json数据。
不需要特别懂里面每一个的含义,只需要知道,前端通过"title"这个键名(key)就可以拿到"合辑护甲"这个值(value)。 "title": "合辑护甲" 这一整个就是俗称的一个字段。通过该字段前端就可以获取到列表的标题了。当然这个列表只是简单的展示用,还有诸如图片地址、优惠信息、已售份额等信息没有提供,这就是缺少字段的情况。
前后端就是通过这样的一个定义获取/传递数据的。
考虑到后期拓展、需求变更等,一般来说,涉及到计算的、可能有变动的,一律不要让前端来弄。
还是刚才那个例子,在刚才那个列表中有一个“立减5元”的橙黄色tag。
这个tag信息,如果考虑不充分,比如说,后端只提供一个数字5,然后前端在其页面写死“立减x元”,x为填入后端提供的数字,颜色固定为橙黄色。这个如果需求不修改还好,如果后期需要新增一个“满20减5元”的红色tag不傻眼了吗?
到时候只能通过升级app来解决,而且不升级的老用户将永远看不到这个红色的tag。
所以说,考虑到程序的可复用和拓展性,需要产品将后期可能新增或变更的需求考虑好,和前后端进行沟通,让前后端设计好实现,尽量降低程序的耦合和硬编码。这才能使一个产品更加健壮以及让苦逼的程序猿少加班的关键。
那么刚才那个tag的需求如何设计才合理呢?
首先是tag显示文字,全权由后端提供,可以是多个字段,由前端进行拼接。然后是tag的颜色,提供几种样式让前端判断是一种可行的办法,但是直接提供tag的色值给前端的这种方式无疑给前端展示增加了无限的可能。
是不是也要增加一个tag形状的字段呢?
俗话说,过犹不及。tag形状这种东西真的很少变更,字段太多无疑会增加开发的时间成本,而且会让人有一种舍本逐末之感。
前端获取到后端数据后,如果前端不主动刷新重新请求数据的话,这个页面的数据在该页面销毁前会一直保持不变。
如何理解?
首先,第一次进入一个页面,该页面数据为空或默认数据。此时前端会链接api请求数据。数据请求完成后,填充进页面。那么本次联网请求就完成了,在前端不进行二次数据请求之前,该页面会一直保持本次请求的数据。也就是说,就算服务端修改了数据,前端此时是不能事实的进行更新的,因为我前端不知道你数据更新了。
那么在这个需要实时更新页面数据的时候和前端讲这种需求会被前端直接回绝:“做不了”。这个时候产品咋办,怪怪妥协?最后背锅的还是自己,而且自己也不知道是真做不了还是假做不了。
实时刷新也不是不能做,只是做的成本略高,需要和后端进行配合,像微信聊天一样和后端进行长连接(socket),这样服务端数据变更前端就知道数据变更了。
当然如果稍懂页面刷新机制的话,可以要求前端在适当的时机进行页面刷新,如在页面可见的时候进行刷新,这样用户每次看到的都是最新的数据。也可以让用户主动刷新,如新增刷新功能。
产品懂技术这件事情,不仅会降低和开发同学沟通时的难度和被歧视风险,还会提升在面对开发同学意见时的判断力,会降低被技术团队忽悠的几率。同时,在需要向上级解释技术原因导致变更的情况下,也会有助于说服老板。
“闻道有先后,术业有专攻”,要相信自己所接触的开发团队是专业的,靠谱的,相信开发团队为实现需求所做出的技术方案是合理的,最优的。如果有质疑,可以加深沟通,以合适的方式提出自己的质疑。这里要补充一句的是,这个信任过程是需要建立的,也是会根据团队的表现不断变化的;同理,其实团队对于产品经理的信任度也是一样的情况。
吐槽是没有意义的,关键还是要解决问题。如果觉得产品经理不靠谱,那么有没有进行过深入的沟通?如果觉得开发不好沟通,那么有没有进行过了解,不好沟通的原因在哪里?如果当事人本身确实不可沟通,那么有没有考虑和对方的老板沟通,或者通过自己的老板如实反映情况?吐槽是最容易的,解决问题反而会很难。
② 前后端分离方案以及技术选型
作者:关开发
一.什么是前后端分离?
理解前后端分离大概可以从3个方面理解:
1. 交互形式
2. 代码组织形式
3. 开发模式与流程
1.1 交互形式
前后端不分离
后端将数据和页面组装、渲染好了之后,向浏览器输出最终的html;浏览器接收到后会解析html,解析引入的css、执行js脚本,完成最终的页面展示。
前后端分离
后端只需要和前端约定好接收以及返回的数据格式(一般用JSON格式),向前端提供API接口。前端就可以通过HTTP请求调用API的方式进行交互。前端获取到数据后,进行页面组装、渲染,最终在浏览器呈现。
1.2 代码组织形式
前后端不分离
在web应用早期的时候,前端页面以及后台业务数据处理的代码都放在一个工程下,甚至放在同一目录下,前端页面夹杂着后端代码。前、后端开发工程师都需要把整套代码导入开发工具才能开发。此阶段下前后端代码以及工作耦合度太高,前端不能独立开发和测试,后端人员也要依赖前端完成页面后才能完成开发。最糟糕的情况是前端工程师需要会后端模板技术(jsp),后端工程师还要会点前端技术,需要口头说明页面数据接口,才能配合完成开发。否则前端只能当一个“切图仔”,只输出HTML、CSS、以及很少量与业务逻辑无关的js;然后由后端转化为后端jsp,并且还要写业务的js代码。
前后端分离
前后端代码放在不同的工程下,前端代码可以独立开发,通过mock/easy-mock技术模拟后端API服务可以独立运行、测试;后端代码也可以独立开发,运行、测试,通过swagger技术能自动生成API文档供前端阅读,还可以进行自动化接口测试,保证API的可用性,降低集成风险。
1.3 开发模式与流程
前后端不分离
在项目开发阶段,前端根据原型和UI设计稿,编写HTML、CSS以及少量与业务无关的js(纯效果那些),完成后交给后台人员,后台人员将HTML转为jsp,并通过JSP的模板语法进行数据绑定以及一些逻辑操作。后台完成后,将全部代码打包,包含前端代码、后端代码打成一个war,然后部署到同一台服务器运行。顶多做一下动静分离,也就是把图片、css、js分开部署到nginx。
具体开发流程如下:图略
前后端分离
实现前后端分离之后,前端根据原型和UI设计稿编写HTML、CSS以及少量与业务无关的js(纯效果那些),后端也同时根据原型进行API设计,并与前端协定API数据规范。等到后台API完成,或仅仅是API数据规范设定完成之后。前端即可通过HTTP调用API,或通过mock数据完成数据组装以及业务逻辑编写。前后端可以并行,或者前端先行于后端开发了。
具体开发流程如下:图略
二、前后端分离的好处与坏处。
从上面3个方面对比了之后,前后端分离架构和传统的web架构相比,有很大的变化,看起来好处多多。到底是分还是不分,我们还是要理性分析是否值得才去做。
从目前应用软件开发的发展趋势来看,主要有两方面需要注意:
· 越来越注重用户体验,随着互联网的发展,开始多终端化。
· 大型应用架构模式正在向云化、微服务化发展。
我们主要通过前后端分离架构,为我们带来以下四个方面的提升:
· 为优质产品打造精益团队
通过将开发团队前后端分离化,让前后端工程师只需要专注于前端或后端的开发工作,是的前后端工程师实现自治,培养其独特的技术特性,然后构建出一个全栈式的精益开发团队。
· 提升开发效率
前后端分离以后,可以实现前后端代码的解耦,只要前后端沟通约定好应用所需接口以及接口参数,便可以开始并行开发,无需等待对方的开发工作结束。与此同时,即使需求发生变更,只要接口与数据格式不变,后端开发人员就不需要修改代码,只要前端进行变动即可。如此一来整个应用的开发效率必然会有质的提升。
· 完美应对复杂多变的前端需求
如果开发团队能完成前后端分离的转型,打造优秀的前后端团队,开发独立化,让开发人员做到专注专精,开发能力必然会有所提升,能够完美应对各种复杂多变的前端需求。
· 增强代码可维护性
前后端分离后,应用的代码不再是前后端混合,只有在运行期才会有调用依赖关系。应用代码将会变得整洁清晰,不论是代码阅读还是代码维护都会比以前轻松。
那么前后端分离有什么不好的地方吗?我目前是没有想到,除非你说会增加前端团队的配备,后端工程师会变的不全能。。。
二、前后端分离架构方案。
实现前后端分离,主要是前端的技术架构变化较大,后端主要变为restfull 风格API,然后加上Swagger技术自动生成在线接口文档就差不多了。
对于目前用于前后端分离方案的前端技术架构主要有两种:
· 传统SPA
· 服务端渲染SSR
2.1 传统SPA
传统SPA指的是单页面应用,也就是整个网站只有一个页面,所有功能都通过这一个页面来呈现。因为一个人的肉眼,某一个时间点看一个页面,既然如此何必要不同功能做多个页面呢?只保留一个页面作为模板,然后通过路由跳转来更新这个模板页面的内容不就可以了吗?确实如此,现在通过reac全家桶、tvue全家桶,模块化、路由、wabpack等技术轻而易举就能实现一个单页面应用。
单页面应用的运行流程
1.用户通过浏览器访问网站url
2.单页面的html文件(index.html)被下载到浏览器,接着下载html里面引用的css,js。
3.css,js下载到浏览器完成之后,浏览器开始解析执行js向后端服务异步请求数据。
4.请求数据完成后,进行数据绑定、渲染,最终在用户浏览器呈现完整的页面。
2.2 服务端渲染
服务端渲染的方案指的是数据绑定,渲染等工作都放在服务端完成,服务端向浏览器输出最终的html。大家看完这个是不是有个疑问,这不是又回到了前后端不分离的时代了吗?答案是否定的,因为这里的服务端是用来执行前端数据绑定、渲染的,也就是把浏览器的一部分工作分担到了服务端。而目前具备这只种能力的服务端是NodeJs服务端。
它的原理其实就是在浏览器与前端代码中间插入了一个NodeJs服务端。浏览器请求前端页面时,会先经过NodeJS服务端,由NodeJs去读取前端页面,并执行异步后端API,获取到数据后进行页面数据绑定,渲染等工作,完成一个最终的html然后返回浏览器,最后浏览器进行展示。
服务端渲染应用的运行流程:
1.用户通过浏览器访问网站url
2.NodeJS服务端接收到请求,读取到对应的前端html,css,js。
3.NodeJS解析执行js向后端API异步请求数据。
4.NodeJs请求数据完成之后,进行数据绑定、渲染,得到一个最终的html。
5.NodeJs向浏览器输出html,浏览器进行展示。
PS:其实本质就是把前端编写成一个nodeJs的服务端web应用。实施服务端渲染后,我们最终运行的是一个Nodejs服务端应用。而单页面应用是把静态页面部署到静态资源服务器进行运行。
看到这里,你是否又有疑问,为什么要这么麻烦搞服务端渲染呢?
2.3 SPA与服务端渲染方案对比
SPA的优点是开发简单,部署简单;缺点是首次加载较慢,需要较好的网络,不友好的SEO。
so,以下就是使用服务端渲染的理由了(摘取vue官方说法):
与传统 SPA (单页应用程序 (Single-Page Application)) 相比,服务器端渲染 (SSR) 的优势主要在于:
· 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
请注意,截至目前,Google 和 Bing 可以很好对同步 JavaScript 应用程序进行索引。在这里,同步是关键。如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax 获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。也就是说,如果 SEO 对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
· 更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。
无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记,所以你的用户将会更快速地看到完整渲染的页面。通常可以产生更好的用户体验,并且对于那些“内容到达时间(time-to-content) 与转化率直接相关”的应用程序而言,服务器端渲染 (SSR) 至关重要。
使用服务器端渲染 (SSR) 时还需要有一些权衡之处:
· 开发条件所限。浏览器特定的代码,只能在某些生命周期钩子函数 (lifecycle hook) 中使用;一些外部扩展库 (external library) 可能需要特殊处理,才能在服务器渲染应用程序中运行。
· 涉及构建设置和部署的更多要求。与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。
· 更多的服务器端负载。在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 (high traffic) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。
以vue为例,实施服务端渲染可以查看官方指南: https://ssr.vuejs.org ,或选择Nuxt.js
2.4 预渲染技术
如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。
如果你使用 webpack,你可以使用 prerender-spa-plugin 轻松地添加预渲染。它已经被 Vue 应用程序广泛测试 - 事实上,作者是 Vue 核心团队的成员。
prerender-spa-plugin: https://github.com/chrisvfritz/prerender-spa-plugin
三、前后端分离技术选型
- artTemplate + bootstrap(不推荐, 不算完全前后端分离)
- vue全家桶(推荐)
- react全家桶 (推荐,生态全)
③ 小程序怎么制作前后端分离的分享模块
创建一个前后端分离项目。
1、前端只需要独立编写客户端代码,后端也只需要独立编写服务端代码提供数据接口即可。
2、前端通过Ajax请求来访问后端的数据接口,将Model展示到View中即可。
3、前后端开发者只需要提前约定好接口文档,然后分别独立开发即可,前端可以造假数据进行测试,完全不需要依赖于后端,最后完成前后端集成即可,真正实现了前后端应用的解耦合,极大地提升了开发效率。
4、前端应用,负责数据展示和用户交互。
5、后端应用,负责提供数据处理接口。
④ 前后端分离,怎么做到服务端渲染
搭车问个问题:
也是打算用 vue,但是如果后端不渲染任何东西,那一个页面可能就有很多请求了。例如,菜单,用户信息,内容等。
是应该合并这些页面的接口吗?还是一个接口返回一类信息,到时接口太多,一个页面十几条 ajax。
⑤ webuploader分片上传的实现代码(前后端分离)
本文介绍了webuploader分片上传的实现代码(前后端分离),分享给大家,具体如下:
WebUploader是由Bai
WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS
6+,
android
4+。两套运行时,同样的调用方式,可供用户任意选用。采用大文件分片并发上传,极大的提高了文件上传效率。(这个是从官网上直接的解释)
功能描述
1、webuploader是网络研发的上传组件,文档不是特别规整,但是也够用了。
2、前端使用官网的上传图片demo,在此基础上代码略微调整做分片。既可以上传图片也可以上传文件。文件超过分片大小才启用分片。
3、分片上传已做md5校验,达到秒传的效果。分片以后需要合并,可以先分片后合并,也可以边分片边合并,本示例采用的是边分片边合并的方案。
4、后端用springboot做框架搭建。springMVC做rest服务,开启跨域访问。
5、容器用springboot内置的tomcat插件,运行Application的main方法即可启动服务;
显示效果
关键代码前端
WebUploader.Uploader.register({
'name':
'webUploaderHookCommand',
'before-send-file':
'beforeSendFile',
"before-send":
"beforeSend"
},
{
beforeSendFile:
function(file)
{
var
task
=
new
WebUploader.Deferred();
fileName
=
file.name;
fileSize
=
file.size;
(new
WebUploader.Uploader()).md5File(file,
0,
10
*
1024
*
1024).progress(function(percentage)
{}).then(function(val)
{
fileMd5
=
val;
var
url
=
checkUrl;
var
data
=
{
type:
0,
fileName:
fileName,
fileMd5:
fileMd5,
fileSize:
fileSize
};
$.ajax({
type:
"POST",
url:
url,
data:
data,
cache:
false,
async:
false,
//
同步
timeout:
1000,
//
todo
超时的话,只能认为该分片未上传过
dataType:
"json",
error:
function(XMLHttpRequest,
textStatus,
errorThrown)
{
file.statusText
=
'server_error';
task.reject();
}
}).then(function(data,
textStatus,
jqXHR)
{
if(data.rtn
==
0)
{
if(data.obj
==
1)
{
file.statusText
=
'file_existed';
task.reject();
}
else
{
task.resolve();
}
}
else
{
task.reject();
}
});
});
return
task.promise();
},
beforeSend:
function(block)
{
var
task
=
new
WebUploader.Deferred();
var
url
=
checkUrl;
var
data
=
{
type:
1,
fileName:
fileName,
fileMd5:
fileMd5,
chunk:
block.chunk,
fileSize:
block.end
-
block.start
};
$.ajax({
type:
"POST",
url:
url,
data:
data,
cache:
false,
async:
false,
//
同步
timeout:
1000,
//
todo
超时的话,只能认为该分片未上传过
dataType:
"json"
}).then(function(data,
textStatus,
jqXHR)
{
if(data.rtn
==
0
&&
data.obj
==
1)
{
task.reject();
//
分片存在,则跳过上传
}
else
{
task.resolve();
}
});
this.owner.options.formData.fileMd5
=
fileMd5;
this.owner.options.formData.chunkSize
=
chunkSize;
return
task.promise();
}
});
//
实例化
uploader
=
WebUploader.create({
pick:
{
id:
'#filePicker',
label:
'点击选择文件'
},
formData:
{
uid:
123
},
dnd:
'#dndArea',
//指定文件拖拽的区域
paste:
'#uploader',
//指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为document.body.
swf:
'../plugins/webuploader/Uploader.swf',
chunked:
true,
chunkSize:
chunkSize,
chunkRetry:
false,
threads:
1,
server:
uploadUrl,
//
runtimeOrder:
'flash',
//
accept:
{
//
title:
'Images',
//
extensions:
'gif,jpg,jpeg,bmp,png',
//
mimeTypes:
'image/*'
//
},
//
禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
disableGlobalDnd:
true,
fileNumLimit:
300
//限制多文件上传的个数
//fileSizeLimit:
200
*
1024
*
1024,
//
限制所有文件的大小
200
M
//fileSingleSizeLimit:
50
*
1024
*
1024
//
限制单个文件的大小
50
M
});
后端
import
java.io.File;
import
java.io.IOException;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
import
org.springframework.beans.factory.annotation.Value;
import
org.springframework.stereotype.Service;
import
org.springframework.web.multipart.MultipartFile;
import
com.bear.upload.util.FileUtil;
import
com.bear.upload.util.RETURN;
import
com.bear.upload.vo.CheckMd5FileVO;
import
com.bear.upload.vo.UploadVO;
@Service
public
class
ChunkUploadService
{
private
static
Logger
LOG
=
LoggerFactory.getLogger(ChunkUploadService.class);
@Value("${file.upload.path}")
private
String
UPLOAD_PATH;
private
static
final
String
Delimiter
=
"-";
/**
*
上传之前校验(整个文件、分片)
*
*
@param
md5FileVO
*
@return
*/
public
Object
check(CheckMd5FileVO
md5FileVO)
{
Integer
type
=
md5FileVO.getType();
Long
chunk
=
md5FileVO.getChunk();
String
fileName
=
md5FileVO.getFileName();
Long
fileSize
=
md5FileVO.getFileSize();
if
(type
==
0)
{//
未分片校验
String
destfilePath
=
UPLOAD_PATH
+
File.separator
+
fileName;
File
destFile
=
new
File(destfilePath);
if
(destFile.exists()
&&
destFile.length()
==
fileSize)
{
return
RETURN.success("文件已存在,跳过",
1);
}
else
{
return
RETURN.success("文件不存在",
0);
}
}
else
{//
分片校验
String
fileMd5
=
md5FileVO.getFileMd5();
String
destFileDir
=
UPLOAD_PATH
+
File.separator
+
fileMd5;
String
destFileName
=
chunk
+
Delimiter
+
fileName;
String
destFilePath
=
destFileDir
+
File.separator
+
destFileName;
File
destFile
=
new
File(destFilePath);
if
(destFile.exists()
&&
destFile.length()
==
fileSize)
{
return
RETURN.success("分片已存在,跳过",
1);
}
else
{
return
RETURN.success("分片不存在",
0);
}
}
}
/**
*
文件上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
upload(MultipartFile
file,
UploadVO
uploadVO)
{
Long
chunk
=
uploadVO.getChunk();
if
(chunk
==
null)
{//
没有分片
return
UnChunkUpload(file,
uploadVO);
}
else
{//
分片
return
ChunkUpload(file,
uploadVO);
}
}
/**
*
分片上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
ChunkUpload(MultipartFile
file,
UploadVO
uploadVO)
{
String
fileName
=
uploadVO.getName();
String
fileMd5
=
uploadVO.getFileMd5();
Long
chunk
=
uploadVO.getChunk();//
当前片
Long
chunks
=
uploadVO.getChunks();//
总共多少片
//
分片目录创建
String
chunkDirPath
=
UPLOAD_PATH
+
File.separator
+
fileMd5;
File
chunkDir
=
new
File(chunkDirPath);
if
(!chunkDir.exists())
{
chunkDir.mkdirs();
}
//
分片文件上传
String
chunkFileName
=
chunk
+
Delimiter
+
fileName;
String
chunkFilePath
=
chunkDir
+
File.separator
+
chunkFileName;
File
chunkFile
=
new
File(chunkFilePath);
try
{
file.transferTo(chunkFile);
}
catch
(Exception
e)
{
LOG.error("分片上传出错",
e);
return
RETURN.fail("分片上传出错",
1);
}
//
合并分片
Long
chunkSize
=
uploadVO.getChunkSize();
long
seek
=
chunkSize
*
chunk;
String
destFilePath
=
UPLOAD_PATH
+
File.separator
+
fileName;
File
destFile
=
new
File(destFilePath);
if
(chunkFile.length()
>
0)
{
try
{
FileUtil.randomAccessFile(chunkFile,
destFile,
seek);
}
catch
(IOException
e)
{
LOG.error("分片{}合并失败:{}",
chunkFile.getName(),
e.getMessage());
return
RETURN.fail("分片合并失败",
1);
}
}
if
(chunk
==
chunks
-
1)
{
//
删除分片文件夹
FileUtil.deleteDirectory(chunkDirPath);
return
RETURN.success("上传成功",
1);
}
else
{
return
RETURN.fail("上传中...",
1);
}
}
/**
*
未分片上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
UnChunkUpload(MultipartFile
file,
UploadVO
uploadVO)
{
String
fileName
=
uploadVO.getName();
//
String
fileMd5
=
uploadVO.getFileMd5();
//
文件上传
File
destFile
=
new
File(UPLOAD_PATH
+
File.separator
+
fileName);
if
(file
!=
null
&&
!file.isEmpty())
{
//
上传目录
File
fileDir
=
new
File(UPLOAD_PATH);
if
(!fileDir.exists())
{
fileDir.mkdirs();
}
if
(destFile.exists())
{
destFile.delete();
}
try
{
file.transferTo(destFile);
return
RETURN.success("上传成功",
0);
}
catch
(Exception
e)
{
LOG.error("文件上传出错",
e);
return
RETURN.fail("文件上传出错",
0);
}
}
return
RETURN.fail("上传失败",
0);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:Vue2.0结合webuploader实现文件分片上传功能使用WebUploader实现分片断点上传文件功能(二)webuploader在springMVC+jquery+Java开发环境下的大文件分片上传的实例代码jQuery
webuploader分片上传大文件
⑥ aspnet怎么实现前后端分离
1、前后端分离,那后端就不应该修改前端项目文件,并且前后端交互都应通过ajax执行。所以,后端只需要提供api,前端在html调用api即可。
2、要提供api的话,aspx也可以做,但因为page的中间件会造成性能的浪费,可以用ashx去做。当然最推荐的还是使用webapi。
更多关于aspnet怎么实现前后端分离,进入:https://m.abcgonglue.com/ask/5114751615595700.html?zd查看更多内容
⑦ 如何进行前后端分离
在不使用vue ,react ,anglar这类的框架的情况下,前后端分离应该如何做?
需求是这样:
前端写html页面(非单页面应用),
index.html 首页
about.html 关于我们
newslist.html 新闻列表
newsdetail.html 新闻详情
proctlist.html 产品列表
proctdetail.html 产品详情
后台只提供json数据
那么
1、前端数据如何渲染?
2、页面跳转是否必须使用路由?(不想使用路由)
3、页面间的数据传递如何做,比如:列表页到详情页的参数传递如何做?