代码如下:
private final static String SPLITER = "-";
private final static String STRING_NULL = "null";
private final static String SLASH = "/";
private final static String SPACE = " ";
private final static String BYTES_EQUALS = "bytes=";
private final static String BYTES_SPACE = "bytes ";
private final static String BYTES = "bytes";
private final static String STRING_EQUALS = "=";
private final static String ZERO_LEFT = "0-";
/**
* 默认缓冲区大小4Kb
*/
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
/**
* 0 从头开始的全文下载
*/
private static final int RANGE_SWITCH_FULL = 0;
/**
* 1 从某字节开始的下载(bytes=[left]-);
*/
private static final int RANGE_SWITCH_LEFT_START = 1;
/**
* 2 从某字节开始到某字节结束的下载(bytes=[left]-[right])
*/
private static final int RANGE_SWITCH_LEFT_TO_RIGHT = 2;
/**
* 从minio下载(二选一-1)
*
* @param protocol minio协议串
* @param response http响应
*/
public void downloadFile(HttpServletRequest request, String protocol, HttpServletResponse response) {
String extension = FilenameUtils.getExtension(protocol);
String mimeType = MediaType.getMimeType(extension);
response.setContentType(mimeType);
if (storeService.exists(protocol)) {
try (InputStream in = storeService.getInputStream(protocol);
OutputStream out = response.getOutputStream()) {
if(mimeType.contains("video/") || mimeType.contains("audio/")){
StorageMetadata metadata = storeService.getMetadata(protocol);
ddxcDownload(request, response, in, out, String.valueOf(metadata.getSize()));
}else {
IOUtils.copy(in, out);
}
} catch (IOException e) {
log.error("从Minio获取文件发生IO异常", e);
}
}
}
/**
* 从网络url下载下载flv文件(二选一-2)
*
* @param protocol minio协议串
* @param response http响应
*/
public void downloadFlv(HttpServletRequest request,
HttpServletResponse response,
@RequestParam String cId) {
String flvUrl = getFlvUrl(cId);
response.setContentType("video/x-flv");
String[] split = StringUtils.split(flvUrl, "/");
response.addHeader("Content-Disposition", "attachment; filename=" + split[split.length-1]);
if (StringUtils.isNotBlank(flvUrl)) {
HttpURLConnection conn = null;
try (OutputStream out = response.getOutputStream()) {
URL url = new URL(flvUrl);
conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(20 * 1000);
Long fileLarge = (long) conn.getContentLength();
InputStream in = conn.getInputStream();
ddxcDownload(request, response, in, out, String.valueOf(fileLarge));
} catch (IOException e) {
logger.error("获取文件发生IO异常", e);
} finally {
Objects.requireNonNull(conn).disconnect();
}
}
}
/*********************************以下为通用断点续传代码**************************************/
/**
* 断点续传,用于预览视频进度条拖动
* @param request request
* @param response response
* @param in minio获取的输入流
* @param out response的输出流
* @param wjdx 文件大小
*/
public void ddxc(HttpServletRequest request, HttpServletResponse response, InputStream in, OutputStream out, String wjdx) {
try(BufferedInputStream bis = new BufferedInputStream(in)) {
long left = 0L;
long right;
//请求下载块大小
long contentLength;
// 0,从头开始的全文下载;1,从某字节开始的下载(bytes=[left]-);2,从某字节开始到某字节结束的下载(bytes=[left]-[right])
int rangeSwitch = RANGE_SWITCH_0;
long fileLength = Long.parseLong(wjdx);
response.reset();
response.setHeader("Accept-Ranges", BYTES);
// 1. 客户端请求下载一个文件块,获取待下载文件块大小
String range = request.getHeader("Range");
if (range != null && range.trim().length() > 0 && !StringUtils.equals(range, STRING_NULL)) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
String rangBytes = range.replaceAll(BYTES_EQUALS, StringUtils.EMPTY);
if (rangBytes.endsWith(SPLITER)) {
// bytes=[left]-
rangeSwitch = RANGE_SWITCH_1;
left = Long.parseLong(rangBytes.substring(0, rangBytes.indexOf(SPLITER)));
// 客户端请求的是[left]之后的字节(包括bytes下标索引为[left]的字节)
contentLength = fileLength - left;
} else {
// bytes=[left]-[right]
rangeSwitch = RANGE_SWITCH_2;
String[] rangBytesArray = rangBytes.split(SPLITER);
left = Long.parseLong(rangBytesArray[0]);
right = Long.parseLong(rangBytesArray[1]);
// 客户端请求的是 [left]-[right] 之间的字节
contentLength = right - left + 1;
}
} else {
contentLength = fileLength;
}
// 2. 如果设设置了Content-Length,则客户端会自动进行多线程下载。
// Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
response.setHeader("Content-Length", Long.toString(contentLength));
// 3. Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
String contentRange;
switch (rangeSwitch){
case RANGE_SWITCH_1:
contentRange = BYTES_SPACE + left + SPLITER + (fileLength - 1) + SLASH + fileLength;
bis.skip(left);
break;
case RANGE_SWITCH_2:
contentRange = range.replace(STRING_EQUALS, SPACE) + SLASH + fileLength;
bis.skip(left);
break;
default:
contentRange = BYTES_SPACE + ZERO_LEFT + (fileLength - 1) + SLASH + fileLength;
}
response.setHeader("Content-Range", contentRange);
// 4. 将该块文件刷出
int n;
long readLength = 0;
byte[] bytes = new byte[DEFAULT_BUFFER_SIZE];
if (rangeSwitch == RANGE_SWITCH_2) {
// 针对 bytes=[left]-[right] 的请求,从[left]开始写数据
while (readLength <= contentLength - DEFAULT_BUFFER_SIZE) {
n = bis.read(bytes);
readLength += n;
out.write(bytes, 0, n);
}
if (readLength <= contentLength) {
n = bis.read(bytes, 0, (int) (contentLength - readLength));
out.write(bytes, 0, n);
}
} else {
while ((n = bis.read(bytes)) != -1) {
out.write(bytes, 0, n);
}
}
out.flush();
}catch (IOException ioe) {
// 忽略 ClientAbortException 之类的异常,断点续传这里会抛很多EOF异常,忽略
}catch (Exception e) {
log.error("断点续传出现异常!", e);
}
}
MediaType.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
/**
* MediaType (资源的媒体类型)
*
* @version 4.0.0
*/
@Slf4j
@Getter
@ToString
@Builder(builderClassName = "Builder")
@AllArgsConstructor
@Accessors(chain = true)
public class MediaType {
/**
* 文件扩展名
*/
private String extension;
/**
* 资源的媒体类型
*/
private String mimeType;
public static final MediaType DEF_TYPE = new Builder().extension("default").mimeType("application/octet-stream").build();
/**
* 获取mimeType(资源的媒体类型)
*
* @param extension 文件扩展名
* @return mimeType(资源的媒体类型)
*/
public static String getMimeType(String extension) {
return Holder.types.getOrDefault(extension, DEF_TYPE).getMimeType();
}
/**
* 获取mimeType(资源的媒体类型)
*
* @param extension 文件扩展名
* @return mimeType(资源的媒体类型)
*/
public static Optional<MediaType> getType(String extension) {
return Optional.ofNullable(Holder.types.get(extension));
}
private static class Holder {
private static Map<String, MediaType> types;
private static final String WHAT = "\r";
static {
List<MediaType> list = new ArrayList<>();
try (InputStream resourceAsStream = MediaType.class.getResourceAsStream("/mime.properties");
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
IOUtils.copy(resourceAsStream, bos);
String s = bos.toString(StandardCharsets.UTF_8.displayName());
String[] stringArray;
if (s.contains(WHAT)) {
stringArray = s.split("\r\n");
} else {
stringArray = s.split("\n");
}
for (String str : stringArray) {
String[] split = str.split("=");
list.add(new Builder().extension(split[0]).mimeType(split[1]).build());
}
} catch (IOException e) {
log.error("", e);
}
types = list.stream().collect(Collectors.toMap(MediaType::getExtension, mimeType -> mimeType));
}
}
}
mime.properties
IVF=video/x-ivf
a11=application/x-a11
acp=audio/x-mei-aac
ai=application/postscript
aif=audio/aiff
aifc=audio/aiff
aiff=audio/aiff
anv=application/x-anv
apk=application/vnd.android.package-archive
asa=text/asa
asf=video/x-ms-asf
asp=text/asp
asx=video/x-ms-asf
au=audio/basic
avi=video/avi
awf=application/vnd.adobe.workflow
biz=text/xml
bmp=image/bmp
bot=application/x-bot
c4t=application/x-c4t
c90=application/x-c90
cal=application/x-cals
cat=application/vnd.ms-pki.seccat
cdf=application/x-netcdf
cdr=application/x-cdr
cel=application/x-cel
cer=application/x-x509-ca-cert
cg4=application/x-g4
cgm=application/x-cgm
cit=application/x-cit
class=java/*
cml=text/xml
cmp=application/x-cmp
cmx=application/x-cmx
cot=application/x-cot
crl=application/pkix-crl
crt=application/x-x509-ca-cert
csi=application/x-csi
css=text/css
cut=application/x-cut
dbf=application/x-dbf
dbm=application/x-dbm
dbx=application/x-dbx
dcd=text/xml
dcx=application/x-dcx
der=application/x-x509-ca-cert
dgn=application/x-dgn
dib=application/x-dib
dll=application/x-msdownload
doc=application/msword
dot=application/msword
drw=application/x-drw
dtd=text/xml
dwf=application/x-dwf
dwg=application/x-dwg
dxb=application/x-dxb
dxf=application/x-dxf
edn=application/vnd.adobe.edn
emf=application/x-emf
eml=message/rfc822
ent=text/xml
epi=application/x-epi
eps=application/x-ps
etd=application/x-ebx
exe=application/x-msdownload
fax=image/fax
fdf=application/vnd.fdf
fif=application/fractals
fo=text/xml
frm=application/x-frm
g4=application/x-g4
gbr=application/x-gbr
gif=image/gif
gl2=application/x-gl2
gp4=application/x-gp4
hgl=application/x-hgl
hmr=application/x-hmr
hpg=application/x-hpgl
hpl=application/x-hpl
hqx=application/mac-binhex40
hrf=application/x-hrf
hta=application/hta
htc=text/x-component
htm=text/html
html=text/html
htt=text/webviewhtml
htx=text/html
icb=application/x-icb
ico=image/x-icon
iff=application/x-iff
ig4=application/x-g4
igs=application/x-igs
iii=application/x-iphone
img=application/x-img
ins=application/x-internet-signup
ipa=application/vnd.iphone
isp=application/x-internet-signup
java=java/*
jfif=image/jpeg
jpe=image/jpeg
jpeg=image/jpeg
jpg=image/jpeg
js=application/x-javascript
jsp=text/html
la1=audio/x-liquid-file
lar=application/x-laplayer-reg
latex=application/x-latex
lavs=audio/x-liquid-secure
lbm=application/x-lbm
lmsff=audio/x-la-lms
ls=application/x-javascript
ltr=application/x-ltr
m1v=video/x-mpeg
m2v=video/x-mpeg
m3u=audio/mpegurl
m4e=video/mpeg4
mac=application/x-mac
man=application/x-troff-man
math=text/xml
mdb=application/x-mdb
mfp=application/x-shockwave-flash
mht=message/rfc822
mhtml=message/rfc822
mi=application/x-mi
mid=audio/mid
midi=audio/mid
mil=application/x-mil
mml=text/xml
mnd=audio/x-musicnet-download
mns=audio/x-musicnet-stream
mocha=application/x-javascript
movie=video/x-sgi-movie
mp1=audio/mp1
mp2=audio/mp2
mp2v=video/mpeg
mp3=audio/mp3
m4a=audio/x-m4a
mp4=video/mp4
mpa=video/x-mpg
mpd=application/vnd.ms-project
mpe=video/x-mpeg
mpeg=video/mpg
mpg=video/mpg
mpga=audio/rn-mpeg
mpp=application/vnd.ms-project
mps=video/x-mpeg
mpt=application/vnd.ms-project
mpv=video/mpg
mpv2=video/mpeg
mpw=application/vnd.ms-project
mpx=application/vnd.ms-project
mtx=text/xml
mxp=application/x-mmxp
net=image/pnetvue
nrf=application/x-nrf
nws=message/rfc822
odc=text/x-ms-odc
out=application/x-out
p10=application/pkcs10
p12=application/x-pkcs12
p7b=application/x-pkcs7-certificates
p7c=application/pkcs7-mime
p7m=application/pkcs7-mime
p7r=application/x-pkcs7-certreqresp
p7s=application/pkcs7-signature
pc5=application/x-pc5
pci=application/x-pci
pcl=application/x-pcl
pcx=application/x-pcx
pdf=application/pdf
pdx=application/vnd.adobe.pdx
pfx=application/x-pkcs12
pgl=application/x-pgl
pic=application/x-pic
pko=application/vnd.ms-pki.pko
pl=application/x-perl
plg=text/html
pls=audio/scpls
plt=application/x-plt
png=image/png
pot=application/vnd.ms-powerpoint
ppa=application/vnd.ms-powerpoint
ppm=application/x-ppm
pps=application/vnd.ms-powerpoint
ppt=application/x-ppt
pr=application/x-pr
prf=application/pics-rules
prn=application/x-prn
prt=application/x-prt
ps=application/x-ps
ptn=application/x-ptn
pwz=application/vnd.ms-powerpoint
r3t=text/vnd.rn-realtext3d
ra=audio/vnd.rn-realaudio
ram=audio/x-pn-realaudio
ras=application/x-ras
rat=application/rat-file
rdf=text/xml
rec=application/vnd.rn-recording
red=application/x-red
rgb=application/x-rgb
rjs=application/vnd.rn-realsystem-rjs
rjt=application/vnd.rn-realsystem-rjt
rlc=application/x-rlc
rle=application/x-rle
rm=application/vnd.rn-realmedia
rmf=application/vnd.adobe.rmf
rmi=audio/mid
rmj=application/vnd.rn-realsystem-rmj
rmm=audio/x-pn-realaudio
rmp=application/vnd.rn-rn_music_package
rms=application/vnd.rn-realmedia-secure
rmvb=application/vnd.rn-realmedia-vbr
rmx=application/vnd.rn-realsystem-rmx
rnx=application/vnd.rn-realplayer
rp=image/vnd.rn-realpix
rpm=audio/x-pn-realaudio-plugin
rsml=application/vnd.rn-rsml
rt=text/vnd.rn-realtext
rtf=application/x-rtf
rv=video/vnd.rn-realvideo
sam=application/x-sam
sat=application/x-sat
sdp=application/sdp
sdw=application/x-sdw
sis=application/vnd.symbian.install
sisx=application/vnd.symbian.install
sit=application/x-stuffit
slb=application/x-slb
sld=application/x-sld
slk=drawing/x-slk
smi=application/smil
smil=application/smil
smk=application/x-smk
snd=audio/basic
sol=text/plain
sor=text/plain
spc=application/x-pkcs7-certificates
spl=application/futuresplash
spp=text/xml
ssm=application/streamingmedia
sst=application/vnd.ms-pki.certstore
stl=application/vnd.ms-pki.stl
stm=text/html
sty=application/x-sty
svg=text/xml
swf=application/x-shockwave-flash
tdf=application/x-tdf
tg4=application/x-tg4
tga=application/x-tga
tif=image/tiff
tiff=image/tiff
tld=text/xml
top=drawing/x-top
torrent=application/x-bittorrent
tsd=text/xml
txt=text/plain
uin=application/x-icq
uls=text/iuls
vcf=text/x-vcard
vda=application/x-vda
vdx=application/vnd.visio
vml=text/xml
vpg=application/x-vpeg005
vsd=application/x-vsd
vss=application/vnd.visio
vst=application/x-vst
vsw=application/vnd.visio
vsx=application/vnd.visio
vtx=application/vnd.visio
vxml=text/xml
wav=audio/wav
wax=audio/x-ms-wax
wb1=application/x-wb1
wb2=application/x-wb2
wb3=application/x-wb3
wbmp=image/vnd.wap.wbmp
wiz=application/msword
wk3=application/x-wk3
wk4=application/x-wk4
wkq=application/x-wkq
wks=application/x-wks
wm=video/x-ms-wm
wma=audio/x-ms-wma
wmd=application/x-ms-wmd
wmf=application/x-wmf
wml=text/vnd.wap.wml
wmv=video/x-ms-wmv
wmx=video/x-ms-wmx
wmz=application/x-ms-wmz
wp6=application/x-wp6
wpd=application/x-wpd
wpg=application/x-wpg
wpl=application/vnd.ms-wpl
wq1=application/x-wq1
wr1=application/x-wr1
wri=application/x-wri
wrk=application/x-wrk
ws=application/x-ws
ws2=application/x-ws
wsc=text/scriptlet
wsdl=text/xml
wvx=video/x-ms-wvx
x_b=application/x-x_b
x_t=application/x-x_t
xap=application/x-silverlight-app
xdp=application/vnd.adobe.xdp
xdr=text/xml
xfd=application/vnd.adobe.xfd
xfdf=application/vnd.adobe.xfdf
xhtml=text/html
xls=application/x-xls
xlw=application/x-xlw
xml=text/xml
xpl=audio/scpls
xq=text/xml
xql=text/xml
xquery=text/xml
xsd=text/xml
xsl=text/xml
xslt=text/xml
xwd=application/x-xwd
文章浏览阅读2.4k次,点赞3次,收藏9次。在写qt网口通信的过程中,遇到中文就乱码。解决方法如下:1.接收端处理中文乱码代码如下 QByteArray-> QString 中文乱码解决: #include <QTextCodec>QByteArray data= tcpSocket->readAll(); QTextCodec *tc = QTextCodec::codecForName("GBK"); QString str = tc->toUnicode(data);//str如果是中文则是中文字符_qbytearray中文乱码
文章浏览阅读2.5k次,点赞2次,收藏15次。什么是 DOM?文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式DOM 树文档:一个页面就是一个文档,DOM 中使用 document 表示元素:页面中的所有标签都是元素,DOM 中使用 element 表示节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node._元素事件
文章浏览阅读1.4k次,点赞3次,收藏7次。关于服务的一些基本知识,包括活动对接口的方法调用,接口实现,服务生命周期等知识。_安卓服务
文章浏览阅读7.9k次,点赞5次,收藏8次。小白式数据库连接池使用,看完拿捏数据库连接池。_采用连接池方式连接数据库
文章浏览阅读4.9k次,点赞5次,收藏36次。摘要:本文介绍了C++11中如何开启新线程,并详细讲解了线程的基础同步原语:mutex, lock_guard, unique_lock, condition variable和semaphore等。如何采用async, packaged_task和promise实现future同步机制?怎样处理spurious wakeup?本文以质数判定服务为例为大家分享C++多线程同步措施!1. C++线程和基础同步原语Thread mutex, lock_guard, unique_lock con._c++线程同步
文章浏览阅读3.3k次,点赞4次,收藏9次。STM32 GPIOx通用输入输出I/O端口的BSRR寄存器与BRR功能简述_gpiob->brr
文章浏览阅读590次。IMP-00019: row rejected due to ORACLE error 12899IMP-00003: ORACLE error 12899 encounteredORA-12899: value too large for column "CRM"."BK_ECS_ORDER_INFO_00413"."POSTSCRIPT" (actual: 895, maximum..._row rejected due to oracle
文章浏览阅读918次。目前很多Web的项目在部署的时候会采用Nginx做为前端的反向代理服务器,后端会部署很多业务处理服务器,通常情况下Nginx代理服务器部署的还是比较少,而且其以高效性能著称,几万的并发连接处理速度都不在话下。然而去年的时候,我们的线上系统也采用类似的部署结构,同时由于我们的业务需求,Nginx的部署环境在虚拟机上面,复用了其他虚拟机的整体磁盘,在高IO消耗的场景中,我们发现Nginx的磁盘_nginx tcp转发 硬盘io
文章浏览阅读645次。Activiti 开发环境的搭建非常简单,主要分为 Activiti runtime 的安装以及 Eclipse 开发环境的配置。本文以 Windows 平台为例介绍 Activiti 5.8 版的开发环境的搭建配置过程。Activiti 的运行时程序可以从http://www.activiti.org/download.html 下载,目前最新版本为 5.8。为了配置使用 Activ_antdev activity
文章浏览阅读2.3k次。1. Vuex 是什么?Vuex 是专门为Vue 组件化思想带来的组件间通信问题提供的解决方案,主要解决以下两个问题:多个视图依赖于同一状态 来自不同视图的行为需要变更同一状态2. 核心概念State: 可以简单理解为Vue 维持的全局变量(状态)。 Getter: 获取State 中的状态的方法,可以在取出前对数据进行二次处理。 Mutation: 是改变State 中的状态..._vuex的组件同级通信
文章浏览阅读8.4k次,点赞31次,收藏33次。逆向中常常出现一些加密算法,如果我们能对这些加密算法进行快速识别则会大大减少我们逆向的难度,虽然IDA已有密码分析神器Findcrypt,但掌握手动分析方法能帮助我们应对更多的情况。这篇文章将介绍逆向中常见的单项散列算法和对称加密算法的识别方法。0xFF. 前言在很长一段时间里我经常发现自己面对复杂的加密算法无从下手,可能是因为还没有系统学过密码学吧orz,总之这个问题困扰了我很久。于是最近我花了一些时间来解决自己在密码学这块的薄弱点,写下这篇文章的目的之一也是为了巩固所学知识。加密算法的部分没有_findcrypt3 支持哪些算法
文章浏览阅读5.3k次。smplayerThere are lots of video players out there, but one that we think gets overlooked is SMPlayer. It can do anything other video players can do and even more – like remembering where you left off ..._sm69影视