日期: 2021 年 4 月 16 日

上传文件到服务器例子,包括前端后台一整套

首先从前端开始:
uploadFile.jsp
<%@ page language=”java” contentType=”text/html; charset=UTF-8″
pageEncoding=”UTF-8″%>
<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>
<title>Insert title here</title>
</head>
<script src=”js/jquery-1.12.0.min.js”></script>
<script src=”js/jquery.form.js”></script>
<body>
<form id=”upfile”>
选择一个文件:
<input type=”file” name=”file” id=”upload” />
<br/><br/>
<input id=”uploadFile” value=”上传” type=”button”/>
</form>

<div id=”upFile”></div>
</body>
<script type=”text/javascript”>

$(“#uploadFile”).click(function(){
var formData = new FormData($(“#upfile”)[0]);
//formData.set(‘file’, document.getElementById(“upload”).files[0]);
$.ajax({
url: ‘${pageContext.request.contextPath}/uploadFile/upload’,
type: ‘POST’,
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function(res) {

});
});
</script>
</html>
上面那个js中注掉的那行,是 直接定位到file那个标签,但是set方法在低版本的浏览器上不支持,会报错只供参考,注意file标签必须是在form里面,记得不能嵌套form,只能有一个form;一般form都是<form method=”post” action=”” enctype=”multipart/form-data” id=”upfile”></form>;我上面例子只是精简了;

前端完成后到后端:
先配置一些参数:
congif.properties(设置上传文件的大小和服务器地址):
#upload
upload.file.maxsize = 104857600
upload.file.url=http://192.168.102.11/test
pom.xml需要引入的jar包

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav-jackrabbit</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>slide</groupId>
<artifactId>slide-webdavlib</artifactId>
<version>2.1</version>
</dependency>

spring配置中需要加下面配置:
<!– 引入配置文件中的参数 –>
<context:property-placeholder location=”classpath:config.properties” />
<!– 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver –>
<bean id=”multipartResolver” class=”org.springframework.web.multipart.commons.CommonsMultipartResolver”>
<property name=”defaultEncoding” value=”UTF-8″></property>
<property name=”maxUploadSize” value=”50485760″></property>
<property name=”resolveLazily” value=”true”></property>
</bean>

<!– 对传入的url进行一些处理,这个<span style=”font-family: Arial, Helvetica, sans-serif;”>UploadFileUtils类所在路径需要根据你实际放置到项目的路径一致,这个类我下面提供了,建完这个类后别忘记把class中的路径替换掉</span>–>
<bean class=”com.yoho.common.UploadFileUtils”>
<property name=”downloadUrl” value=”${upload.file.url}”/>
</bean>
UploadFileUtils.java(这个类主要是对config中的url参数的一些处理)
import org.apache.commons.lang3.StringUtils;

public class UploadFileUtils {

public static String downloadUrl = null;

/**
* *对路径与相对路径转换
*/
public static String addPrefix(String url) {
// 本身就是*对路径直接返回
if (url == null || url.startsWith(“http://”) || url.startsWith(“https://”)) {
return url;
}
return URLUtils.append(downloadUrl, url);
}

public static String removePrefix(String url) {
// 如果 url 不符合条件,直接返回
if (url == null || !url.startsWith(downloadUrl)) {
return url;
}
return StringUtils.removeStart(url, downloadUrl);
}

public void setDownloadUrl(String downloadUrl) {
UploadFileUtils.downloadUrl = downloadUrl;
}
}
controller接收请求:
UploadFile.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.yoho.model.FileInfo;
import com.yoho.service.UploadService;

/**
* @author zelei.fan
*
*/
@Controller
@RequestMapping(“/uploadFile”)
public class UploadFile{

@Autowired
private UploadService uploadService;
/**
* 需要在spring-mvc中配置MultipartFile相关信息,以及引进fileUpload的依赖
* @param multipartFile
* @return
* @throws Exception
*/
@RequestMapping(value = “/upload”, method = RequestMethod.POST)
@ResponseBody
public FileInfo upload(@RequestParam(“file”)MultipartFile multipartFile)throws Exception{

FileInfo fileInfo = uploadService.uploadFile(multipartFile);
return fileInfo;
}

}
实体类,封装了一些属性,文件名,文件类型,相对地址,*对地址
FileInfo.java
public class FileInfo {

private String fileName;

private String fileType;

private String absoluteUrl;

private String relativeUrl;

private String fileSize;

private String fileMd5;

private String createAt;

public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

public String getFileType() {
return fileType;
}

public void setFileType(String fileType) {
this.fileType = fileType;
}

public String getAbsoluteUrl() {
return absoluteUrl;
}

public void setAbsoluteUrl(String absoluteUrl) {
this.absoluteUrl = absoluteUrl;
}

public String getRelativeUrl() {
return relativeUrl;
}

public void setRelativeUrl(String relativeUrl) {
this.relativeUrl = relativeUrl;
}

public String getFileSize() {
return fileSize;
}

public void setFileSize(String fileSize) {
this.fileSize = fileSize;
}

public String getFileMd5() {
return fileMd5;
}

public void setFileMd5(String fileMd5) {
this.fileMd5 = fileMd5;
}

public String getCreateAt() {
return createAt;
}

public void setCreateAt(String createAt) {
this.createAt = createAt;
}

}

然后到service中进行业务处理:
UploadService.java(业务处理接口)
import org.springframework.web.multipart.MultipartFile;

import com.yoho.model.FileInfo;

public interface UploadService {

/**
* 上传文件,返回链接
* @param multipartFile
* @return
*/
FileInfo uploadFile(MultipartFile multipartFile);

}

具体的实现类:
UploadServiceImpl.java
import static com.google.common.base.Preconditions.checkArgument;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.httpclient.HttpURL;
import org.apache.webdav.lib.WebdavResource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.PeekingIterator;
import com.yoho.common.DateUtil;
import com.yoho.common.MD5;
import com.yoho.model.FileInfo;
import com.yoho.service.UploadService;

/**
*
* @author zelei.fan
*
*/
@Service
public class UploadServiceImpl implements UploadService{

@Value(“${upload.file.url}”)
private String uploadUrl;

@Value(“webdav”)
private String uploadUsername;

@Value(“webdav”)
public String uploadPassword;

@Override
public FileInfo uploadFile(MultipartFile multipartFile) {

//取到文件大小,如果超过指定范围的话就直接返回提醒错误
long size = multipartFile.getSize();
//获取文件名
String fileName = multipartFile.getOriginalFilename();
// 获取文件后缀,即文件类型
String fileExt = “”;
if (fileName.contains(“.”)) {
fileExt = fileName.substring(fileName.lastIndexOf(“.”) + 1).toLowerCase();
}
//设置MD5加密
String fileMD5 = md5File(multipartFile);

//拼接文件路径:/后缀/年/月/日/md5/filename
String saveUrl = “/” + fileExt + new SimpleDateFormat(“/yyyy/MM/dd/”).format(new Date()) + fileMD5 + “/” + multipartFile.getOriginalFilename();

String location = null;
try {
location = saveFile(multipartFile, saveUrl);//保存文件操作
} catch (Exception e) {
e.printStackTrace();
}

FileInfo fileInfo = new FileInfo();
fileInfo.setAbsoluteUrl(location);
fileInfo.setRelativeUrl(saveUrl);
fileInfo.setFileMd5(fileMD5);
fileInfo.setFileName(fileName);
fileInfo.setFileSize(String.valueOf(size));
fileInfo.setFileType(fileExt);
fileInfo.setCreateAt(DateUtil.date2String(new Date(), DateUtil.DATE_TIME_FORMAT));
return fileInfo;

}

//MD5加密
private String md5File(MultipartFile multipartFile) {
try {
return MD5.md5(multipartFile.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

private String saveFile(MultipartFile file, String savePath) throws Exception {
// 上传文件,到文件服务器,uploadUrl是在config中配好的,就是给uploadUrl赋值,如果不用那么麻烦的话可以直接把url放进去:upload(“http://192.168.102.11/test”, uploadUsername, uploadPassword, savePath, file.getBytes());
upload(uploadUrl, uploadUsername/*那台服务器的用户名*/, uploadPassword/*那台服务器的密码*/, savePath, file.getBytes());
return append(uploadUrl, savePath);

}

public static void upload(String webDavServer, String webDavUser, String webDavPassword, String remotePath, byte[] bytes) throws IOException {

if (!webDavServer.endsWith(“/”)) webDavServer += “/”;

//连接服务器
HttpURL hrl = new HttpURL(webDavServer);
hrl.setUserinfo(webDavUser, webDavPassword);

WebdavResource wdr = new WebdavResource(hrl);

//make directory if need
StringBuffer ssdir = new StringBuffer();
// 去除*后一个文件名
StringTokenizer t = new StringTokenizer(remotePath.substring(0, remotePath.lastIndexOf(“/”)), “/”);
while(t.hasMoreTokens()){
String sdir = t.nextToken();
ssdir.append(sdir+”/”);
wdr.mkcolMethod(wdr.getPath() + ssdir );
}

String remoteFile= wdr.getPath() + remotePath;//拼成*对地址
boolean result = wdr.putMethod(remoteFile, bytes);//把文件写进去
checkArgument(result, “文件上传出错”);//false时会报错,true则为成功

wdr.close();//*后关闭连接

}

/**
* 连接 URL
* @param paths
* @return
*/
public static String append(String… paths) {
List<String> pathList = Lists.newArrayList(paths);
PeekingIterator<String> iter = Iterators.peekingIterator(pathList.iterator());
StringBuilder urlBuilder = new StringBuilder();
while (iter.hasNext()) {
String current = iter.next();
urlBuilder.append(current);
if (!iter.hasNext()) {
break;
}
if (current.endsWith(“/”) && iter.peek().startsWith(“/”)) {
urlBuilder.deleteCharAt(urlBuilder.length() – 1);
} else if (!current.endsWith(“/”) && !iter.peek().startsWith(“/”)) {
urlBuilder.append(“/”);
}
}
return urlBuilder.toString();
}

}
所有的代码都已经在上面了,我已经测试过能上传成功,相应方法的注释页标在上面,希望你能运行成功;如果有什么问题可以留言给我,尽量能帮到你

什么是主流的开发安卓APP的方式?

IDE
曾经的主流,Eclipse+Genymotion

1. 安装Genymotion

默认的虚拟机启动及其困难,也较为卡顿,这时候我们需要一个替代的虚拟机Genymotion了

当然前提是你要有个账号。

下载安装过程就不细说了,选择教育|学习|个人使用版本就行了。

安装完毕后,打开,用账户登陆(没有就去注册),下载自己想要的虚拟机版本,设置分辨路和内存。


2. Genymotion和Eclipse链接

至于链接就需要装个插件了,和安装ADTPlugin一样,
01

接着输入插件地址:http://plugins.genymotion.com/eclipse

02

然后等待以下,把下面选项 Group items by category 选项勾弄掉,接着就出现插件包了,选上就Next,同意,无乱什么都选择Yes,等待下载安装直到完成。

下载安装完成重启Eclipse后会发现多了个这个图标
04

点击以下,会弹出警告,让你设置Genymotion和安装目录,设置你刚才安装的Genymotion的目录,接着确定就行了。

剩下的就一样的了,点击上面那个图标打开虚拟机,然后选择启动虚拟机。

在运行项目之前,先设置以下运行配置
05

选择如下
06


现在的主流,AndroidStudio+Genymotion

1. 安装Android Studio

AndroidStudio的下载地址在下面 ↓ (不要怀疑(→_→),下面那个就是是谷歌官网下载地址)

https://dl.google.com/dl/android/studio/install/2.2.0.12/android-studio-bundle-145.3276617-windows.exe

安装过程同样不在多说,一直下一步到完成就行了。

特别注意!
安装路径不要出现任何中文!!!
不要出现任何中文!!!
不要出现任何中文!!!

2. Android Studio和Genymotion链接

Genymotion安装上面已讲,Android Studio链接Genymotino同样是安装插件,很简单,打开设置
07

在Plugins选项中输入genymotion,搜索到后点击旁边的install,因为我安装了所以显示“Uninstall”
08

如果搜不到就点击下面搜索进行安装
09

一直同意,Next,等待安装完毕后重启。

重启后出现下面的图标。
10

点击打开,会弹出错误,说没设置Genymotion目录,和上面一样,到设置里设置。
11

后面就一样的了,点击小图标来选择启动虚拟机,接着运行项目。

前端上传文件到服务器端

上传文件到服务器有很多插件,而且各种UI组件库,像iview,eleUI也都替我们封装好了,根本不用我们操心。
下面是原生的form 上传
原生form表单上传文件
直接上代码

<form enctype=’multipart/form-data’ action=”http://192.168。xxx.xxx:3000/upload” method=”post”>
<input type=”file” name=’pic’>
<input type=”submit”>
</form >

首先我们看form的enctype 属性
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。默认地,表单数据会编码为 “application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码,但是在这里上传文件,我们用multipart/form-data,通过二进制方式提交。

action是你上传文件的地址路径,method是以什么方式进行处理,post为上传,get为获取。
前端很简单,重要的是后端,博主用node起了一个服务器,废话不说,上代码

var multiparty = require(‘multiparty’)

router.post(‘/upload’,function (req,res) {
//创建处理form表单的对象
var form = new multiparty.Form({
uploadDir: ‘./images’
})//文件上传的路径
//通过form.parse生成服务器文件,注意这里生成的文件名字不是原来的名字,而是编码后的名字,里面的回调包含错误信息,字段信息,文件信息
form.parse(req,function (err,fields,files) {
if(err) {throw err ;
console.log(err)}
else{
res.send(JSON.stringify(files.pic[0]))
}
})
})

这里需要安装插件multiparty
执行命令npm i multiparty
作用:使用内容类型解析http请求multipart/form-data,也称为文件上载。

HTTP流媒体播放技术发展以及nginx点播源站

互联网多媒体内容传输从大方向上可以分为下载传输和流式传输,而流式传输又可以分为顺序流式传输和实时流式传输,换句话来说就是点播(Video on Demand)和直播(Live Streaming),顾名思义,前者的媒体内容是提前存储在服务器上供客户端请求播放,而后者是实时产生并分发给客户端播放。

本文主要是基于HTTP的流媒体点播技术入门,讲述了一些基本的概念以及这一技术的变革演进。

互联网上传播音视频内容*早从上世纪90年代开始,RTP等专有协议的提出就是定义音视频的包格式以获得更低的网络传递开销。不过现如今的互联网世界,CDN扮演着非常重要的角色,而*大部分CDN厂商是不支持RTP等协议的。基于HTTP的流媒体点播技术则占据着主流,其有几点优势:1、防火墙友好;2、客户端控制媒体流的访问,服务端不需要为每一个客户端连接维护媒体session状态;3、采用标准的HTTP服务器即可,支撑大规模客户端访问不需要额外的服务器技术资源开销,*重要的就是CDN技术的良好支持优化。

HTTP流媒体技术的变革大致经过了以下四个阶段:

 

*初,我们只能先下载完整视频文件到本地磁盘后,然后才能播放观赏。这意味着你必须等待视频下载操作的完成,严格来讲,根据我们*段的划分,这不能称作为流媒体传输,不过我们还是列出来,以作对比。

 

在上面简单下载文件的基础上,一个明显的提升就是渐进式下载技术。这种情况下不需要完整下载视频文件,可以边下载边播放,这就要求视频的元数据信息得放在视频文件的开头。但是,我们只能在已经下载的那一部分自由拖拽播放,而未下载的部分是不能播放的。

 

在渐进式下载的基础上,pseudo-streaming(伪流)出现了,其增强了seek播放功能,也就是支持直接切到未下载的地方进行观看,所以也可以称之为渐进式播放。

 

其实,到pseudo-streaming 这一步,流媒体播放的技术已经很成熟了,而且目前*大多数的视频网站都是这种技术,比如Youtube、优酷、腾讯视频等。如果,要在这个基础上再一步的优化,可以从哪些方面呢?比较容易想到的就是带宽优化,能够链路感知,这就是下面的自适应比特率流。其原理就是,同一视频内容会有不同的码率版本,客户端播放器会动态地根据网络质量切换请求带宽匹配的的视频片段。

 

自适应码率流媒体技术,业内比较常见的实现是Apple的HTTP Live Streaming (HLS)以及Adobe的HTTP Dynamic Streaming (HDS),下图简单展示了HLS的文件结构,可以看到master playlist包含了两种不同码率的播放列表,当然如果你只有一种版本,那么就不需要master playlist了。基于HTTP的自适应码率流媒体是有国际标准的,那就是3GPP组织和MPEG小组所提出的MPEG-DASH(Dynamic Adaptive Streaming over HTTP)。

 

*后,我们来说说一个简单的点播流媒体服务器是怎么工作的。

目前,很常见的一种搭建方式就是基于nginx,而nginx本身对音视频媒体的处理就有一定的支持,官方就有flv和mp4的插件,即ngx_http_flv_module和ngx_http_mp4_module。前者支持以字节偏移的渐进式seek播放,后者支持以时间偏移的渐进式seek播放。

要想达到这种渐进式播放的目的,大部分情况下,我们是要对服务端的媒体文件进行一定的处理的。首先播放之前,服务端需要先返回一定的视频元数据信息,其次我们需要知道媒体时间和媒体数据的映射关系。为什么呢?

目前大部分的视频编码都采用H264标准,而H264的不同视频帧采用了不同的压缩编码方式,其中I帧的作用很大,其通常是每个 GOP(Group of Picture)的*个帧,我们简单点说,I帧依靠自身就可以解码出完整图像,而其后面帧的解码则需要依赖I帧,这意味着什么?

是的,这决定了我们在拖拽播放的时候,播放器会seek到*近的I帧处,所以有时候会有一个现象,就是你拖到一个精确的时间点,但是播放器却在另一个靠近的时间点开始播放,这就是因为那个时间点是I帧所在之处。

播放器的seek播放通常是让用户选择时间偏移,而服务端*终对文件的请求处理只能是字节偏移,所以问题来了,我们要有一个时间偏移和字节偏移的映射表,严格一点说,是每一个I帧的时间偏移与字节偏移映射。

问题又来了,这个映射是放在客户端还是服务端处理呢?当然是都可以。如果客户端发出字节偏移请求,那么服务端就很轻松,只需要提供HTTP range访问的功能,但是client端需要提前知道时间与字节的映射关系,比如flv格式的metadata就提供了这个信息,有的flv文件没有加入metadata,这时候就需要用相应的flv工具(比如flvmeta)去处理成这样的格式,这样客户端的播放器就可以直接发送字节偏移量了。MP4则不需要这么处理,因为MP4格式本身就要求带这样的信息,其记录metadata的Movie Box (moov)中的Media Information Box (minf)就存储了媒体时间和媒体数据的映射关系。如果客户端只发出时间请求,那么服务端就得将时间偏移请求转换为字节偏移请求,然后处理并响应请求。

上面讲了这么多,那请问,在哪里可以买到牛逼的点播服务呢?

网易视频云推出的一站式视频云点播平台,基于分布式处理集群和大规模分发系统资源,满足全终端设备的播放需求,为企业用户提供*速稳定的视频上传、存储、转码、播放和下载等云服务,欢迎试用购买。

python读写文本文件

python读写文本文件

主要参考菜鸟教程:https://www.runoob.com/python/file-methods.html

?读文件
以读一个列表txt文件(列表内容是字符串,不是数字,如果是数字,可以直接用numpy进行读写)为例,得到一个list

# 可以使用encoding规定编码
# 读文件时,模式参数一般为r,表示以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
with open(“xxx.txt”,”r”,encoding=”utf8″) as f:
rslist=[]
for i in f.readlines():
rslist.append(i.strip())
# 由于使用readlines()或realine()方法都会把换行符读进去,所以使用strip()方法处理一下再加入到列表中

?写文件
要把一个字符串列表写入到一个txt文本文件中(如果直接复制的话,会有很多引号,所以还是采取程序写的方式好些),代码示例如下:

# 这里要注意的是 模式
writelist=[i+”\n” for i in rslist]
with open(“123.txt”,’a’,encoding=’utf8′) as f:
f.writelines([“123\n”,”1″])
f.writelines(writelist)

*常见的几种文件读写模式:
%title插图%num

nginx搭建基于http协议的视频点播服务器

1,于由自己的服务器上已经安装好nginx(具体安装方法见我的另一篇文章,Linux中安装nginx),所以不再安装。

2,下载nginx_mod_h264_streaming-2.2.7.tar.gz(自己在网上搜吧)。

3,安装pcre,先看有没有安装。

 

[root@localhost vsftpd]# rpm -qa pcre
pcre-7.8-7.el6.i686

已经安装(上篇加rtmp模块的时候已经安装了)

4,解压nginx_mod_h264_streaming-2.2.7.tar.gz,添加flv,mp4模块。解压到和nginx源码同级的目录。然后./configure –add-module=../nginx_mod_h264_streaming-2.2.7 –with-http_flv_module –with-http_mp4_module
因为flv 和http是nginx自带的所以不用下载这个模块。

5,make
可能遇到问题1
/root/nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c: In function ‘ngx_streaming_handler’:
/root/nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c:158: error: ‘ngx_http_request_t’ has no member named ‘zero_in_uri’
make[1]: *** [objs/addon/src/ngx_http_h264_streaming_module.o] Error 1
make[1]: Leaving directory `/root/nnginx-1.5.9′
make: *** [build] Error 2
那么将src/ngx_http_streaming_module.c文件中以下代码删除或者是注释掉就可以了

6, make install

7,配置 nginx.conf
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
worker_connections  1024;
}

#include  nginx.conf-rtmp;

http {

include       mime.types;

default_type  application/octet-stream;

log_format main  ‘$remote_addr – $remote_user [$time_local] ‘

‘”$request” $status $bytes_sent ‘

‘”$http_referer” “$http_user_agent” ‘

‘”$gzip_ratio”‘;

keepalive_timeout  60;

server_names_hash_bucket_size  128;

client_header_buffer_size    32k;

 

large_client_header_buffers  4 32k;

 

access_log off;

gzip on;

gzip_min_length  1100;

gzip_buffers     4 8k;

gzip_types       text/plain;

 

output_buffers   1 32k;

postpone_output  1460;

 

client_header_timeout  3m;

client_body_timeout    3m;

send_timeout           3m;

 

sendfile                on;

tcp_nopush              on;

tcp_nodelay             on;

 

######################################################################

 

server {

listen       8999;

server_name  192.168.1.104;

root    /usr/local/nginx/html/flv_file/;

limit_rate_after 5m;
limit_rate 512k;

index   index.html;

charset utf-8;

location ~ \.flv {

flv;

}

location ~ \.mp4$ {
mp4;
}

error_page   500 502 503 504  /50x.html;

location = /50x.html {

root   html;

}
}

}

8,启动nginx,创建 /usr/local/nginx/html/flv_file/目录。

9,上传mp4视频文件CY.mp4。

10,写个html测试。看之前的文章用jwplayer来测试,但是我这边一直报jwplayer udefined。

<!DOCTYPE html>
<div id=”container”>Loading the player …</div>
<video src=”http://192.168.1.104:8999/CY.mp4″ controls=”controls” width=”50%” height=”50%”>
</video>

云计算是IDC未来发展的趋势,具体是什么?

云计算是IDC未来发展的趋势。

1、节能降耗

在能源成本方面,每台瘦客户机相对于每台PC机,PC机每年耗能成本是瘦客户机的约6.25倍。

2、维护成本基本可以忽略不计,虚拟化平台的瘦终端是分散安装,集中管理,服务独享。这样不仅解决了客服电话座席营销问题,而且99%的故障都可在 服务端集中解决,每年维护费均摊后基本可忽略不计;原有PC是分散安装,分散维护方式,设备损坏更换费用就更大了,更主要的是,由于营业网点分散,维护中 大量时间消耗在远程路途上,维护功效很低。

3、系统稳定可靠,且能长时间运行通过数据集中改善桌面管理,提高数据与系统安全,有效提高系统的稳定可靠性。另外,数据中心的服务器与部署在桌面 的瘦客户机在设计方面都具有更高的可靠性,整机寿命长,支持长时间连接工作;在虚拟化技术方面,其还具有DRS、HA、FT等高级特性,这些都有效保证了 系统的稳定可靠连续运行。

4、实现管理集中,提高可管理和可维护性通过应用、桌面、用户数据的集中,真正实现IT的集中管理,无需管理员再到坐席对每台PC进行单点维护,大大提高可管理和可维护性。

5、节能环保、无噪音,营造更为安静舒适的工作环境瘦客户机采用高速超低功耗CPU及先进的散热技术设计,整机无风扇,功耗低,节能环保无噪音,更易营造安静舒适的呼叫中心工作环境。

6、可管理性

模块化(“分而治”)的概念将更容易在控制台查看和计算接入数量的要求。

7、安全性高

瘦客户机与现有终端安全机制紧密结合,实现与使用物理PC时一样的严格准入以及权限控制。对于用户配置文件的可见性增强使用的安全性。在任何站点的修改必须采用远程管理,并对该操作进行录像审计,因此具有高度安全性。

Appium+Python3+iOS真机环境搭建

Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用。
1.环境配置
Mac系统自带的Python版本是2.7,当前要用新版,这里我选择的Python版本是3.5。下载安装。
删除掉mac自带的python2.7
sudo rm -R /System/Library/Frameworks/Python.framework/Versions/2.7
加上:
alias python=’/Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5’
保存退出,执行:
source ~/.bash_profile
2,把appium和selenium安装到python3.5的set-packages中
3,appium运行时jdk的安装
访问Oracle官网 http://www.oracle.com
jdk下载的地方https://www.oracle.com/technetwork/java/javase/downloads/jdk11-downloads-5066655.html
下载安装jdk,打开Finder,可以在下图所示的路径中找到安装好的jdk 1.8.0_40.jdk
%title插图%num

Contents下的Home文件夹,是该JDK的根目录

%title插图%num

打开终端配置jdk环境变量:
如果你是*次配置环境变量,可以使用“touch .bash_profile” 创建一个.bash_profile的隐藏配置文件(如果你是为编辑已存在的配置文件,则使用”open -e .bash_profile”命令):
输入如下配置:

%title插图%num

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
PATH=$ JAVA_HOME/bin:$ PATH:.
CLASSPATH=$ JAVA_HOME/lib/tools.jar:$ JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export PATH
export CLASSPATH
然后保存关闭该窗口。
使用”source .bash_profile”使配置生效
输入 echo $ JAVA_HOME 显示刚才配置的路径
测试输入java -version
4,sdk环境变量的配置
在命令行输入 open -e .bash_profile , 打开.bash_profile文件,输入如下配置:
export ANDROID_HOME=/Library/Java/sdk
export PATH=$ {PATH}: $ {ANDROID_HOME}/tools
export PATH=$ {PATH}: $ {ANDROID_HOME}/platform-tools
export PATH=$ {PATH}: $ {ANDROID_HOME}/build-tools

export PATH=${PATH}:/Library/Java/sdk/platform-tools:/Library/Java/sdk/tools
%title插图%num

然后保存并关闭。
在命令行输入source .bash_profile ,使之生效。
5,ios的元素定位工具
a.Appium自带的Inspector工具
b.Macaca的app-inspector工具,具体地址:https://macacajs.github.io/app-inspector/cn/
c.Xcode自带的accessibility-inspector工具
具体地址:http://blog.csdn.net/icetime17/article/details/42211915
d.Appium团队提供的appium-ios-inspector
具体地址:https://github.com/mykola-mokhnach/Appium-iOS-Inspector
e.通过flex插件,具体地址:https://github.com/Flipboard/FLEX

的正约数

的正约数

蓝桥杯求100!的正约数
这个问题猛地一看好像不能用暴力求解,他就是不能用暴力求解,因为这个数太大了。

怎么解决

1、首先我们要把1*2*3…100的质因数全部求出来。

​ 用暴力求解去遍历1~100,每个数的质因数,然后存在一个result的全局列表中

2、在计算每个质因数出现的次数,这里我用的是字典存储每个数字出现的次数

这里涉及到一个计算公式
$$
整数=质因数n*质因数m

$$

整 数 的 约 数 的 个 数 = ( n + 1 ) ∗ ( m + 1 ) 整数的约数的个数=(n+1)*(m+1)
整数的约数的个数=(n+1)∗(m+1)

例如
$$
12=223=2^2*3

12 的 约 数 的 个 数 就 是 n 12的约数的个数就是n
12的约数的个数就是n

n=(2+1)*(1+1)
$$
他们分别是1,2,3,4,6,12

100!的代码
result = [] # 存取所有的质因数
dirct = {} #存放质因数出现的次数

count = 1
def demo(n):#求解质因数的函数
k = 2
global result
while n > 1:
if n % k == 0:
result.append(k)
n = n / k
else:
k += 1

# 求解每个数的质因数
for i in range(2, 101):
demo(i)
print(result)

# 记录每个质因数出现的次数
for i in result:
if i not in dirct.keys():
dirct[i] = 1
else:
dirct[i] += 1
print(dirct)#质因数出现的次数

# 计算约数出现的次数
for values in dirct.values():
count *= (values + 1)

print(count)

python 字典黑魔法

python 字典黑魔法

python中三大数据结构,列表、字典、集合,字典是平时处理数据所用到的做多的,以此记录几个字典使用时黑魔法(骚操作)。

有一个原始序列数据:

info = {
“info1”:
{“name”: “Limin”, “age”: 20, “height”: 176, “score”: 90},
“info2”:
{“name”: “jenny”, “age”: 14, “height”: 140, “score”: 98},
“info3”:
{“name”: “tonya”, “age”: 26, “height”: 180, “score”: 82},
“info4”:
{“name”: “suyoo”, “age”: 22, “height”: 165, “score”: 89},
}

1. 字典排序
现在需要将 info按照身高进行排序,并输出到一个列表里。当然是选择so strong
的*sorted() 函数了

In [2]: info
Out[2]:
{‘info1’: {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
‘info3’: {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82},
‘info4’: {‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89}}

In [3]: sorted(info.items(), key=lambda x: x[1][‘height’])
Out[3]:
[(‘info2’, {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98}),
(‘info4’, {‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89}),
(‘info1’, {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90}),
(‘info3’, {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82})]

现在需要是需要升高由大到小呢

In [4]: sorted(info.items(), key=lambda x: x[1][‘height’], reverse=True)
Out[4]:
[(‘info3’, {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82}),
(‘info1’, {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90}),
(‘info4’, {‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89}),
(‘info2’, {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98})]

如果不想要infox字样了呢,so easy

In [5]: sorted(info.values(),key=lambda x:x[‘height’])
Out[5]:
[{‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
{‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89},
{‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
{‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82}]

so,可以看到字典暗黑魔法之一的 sorted() 是不是very强大,不过此处需要注意的是***info***字典本身并没有发生变化,变化的仅是返回值

2. 字典数据筛选(字典推导式)
现在需要筛选出***info***中成绩大于等于90的学生信息,这时候就该写一个函数了。

result={}
for key,value in info.items():
for i,k in value.items():
if i == “score” and k >= 90:
result[key]=value
print(result)

>>>
{‘info1’: {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98}}

是不是看似很完美,but,python中有一个叫 推导式(划重点)的东西,为何不用呢

In [9]: info
Out[9]:
{‘info1’: {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
‘info3’: {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82},
‘info4’: {‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89}}

In [10]: {key:value for key,value in info.items() if value[“score”] >= 90}
Out[10]:
{‘info1’: {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98}}

结果一模一样有木有,仅仅一行代码,很强大的推导式。

3. 字典的计算
现在需要取出info中成绩*好和*坏的两名学生,当然不是用目测法。假如1000条数据,我相信目测法还是可以试试的。
还是先用万能的函数吧。

# 函数
result={}
score= [x[“score”] for x in info.values()]
for key,value in info.items():
for i,k in value.items():
if i == “score” and k in [max(score), min(score)]:
result[key]=value
print(result)
>>>
{‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
‘info3’: {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82}}

# 列表推导式法
score= [x[“score”] for x in info.values()]
print({k:v for k,v in info.items() if v[“score”] in [max(score), min(score)]})
>>>
{‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
‘info3’: {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82}}

4. 字典的键值翻转(一道经典面试题)
就是将上面***info***字典中的值(也就是第二层字典)中的键值对调,假如不存在重复键的情况。

# 函数解法
result = {}
for key, value in info.items():
result1 = {}
for i,v in value.items():
result1[i]=v
result[key] = result1
print(result)

>>>
{‘info1’: {176: ‘height’, 20: ‘age’, 90: ‘score’, ‘Limin’: ‘name’},
‘info2’: {14: ‘age’, 140: ‘height’, 98: ‘score’, ‘jenny’: ‘name’},
‘info3’: {180: ‘height’, 26: ‘age’, 82: ‘score’, ‘tonya’: ‘name’},
‘info4’: {165: ‘height’, 22: ‘age’, 89: ‘score’, ‘suyoo’: ‘name’}}

再来看看推倒式解法,一句话,有木有很强大

In [28]: info
Out[28]:
{‘info1’: {‘age’: 20, ‘height’: 176, ‘name’: ‘Limin’, ‘score’: 90},
‘info2’: {‘age’: 14, ‘height’: 140, ‘name’: ‘jenny’, ‘score’: 98},
‘info3’: {‘age’: 26, ‘height’: 180, ‘name’: ‘tonya’, ‘score’: 82},
‘info4’: {‘age’: 22, ‘height’: 165, ‘name’: ‘suyoo’, ‘score’: 89}}
In [29]: {k:{i:v for v,i in info[k].items()} for k in info}
Out[29]:
{‘info1’: {176: ‘height’, 20: ‘age’, 90: ‘score’, ‘Limin’: ‘name’},
‘info2’: {14: ‘age’, 140: ‘height’, 98: ‘score’, ‘jenny’: ‘name’},
‘info3’: {180: ‘height’, 26: ‘age’, 82: ‘score’, ‘tonya’: ‘name’},
‘info4’: {165: ‘height’, 22: ‘age’, 89: ‘score’, ‘suyoo’: ‘name’}}

 

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速