文件上传与下载与文件服务器知识概括

文件上传与下载与文件服务器知识概括

文件上传与下载

常见文件上传方式:

  • 我们知道,前端上传文件时,最常见的就是利用Form表单的方式进行文件的上传功能了,上传时设置enctype为multipart/form-data,或者直接利用jquery的一些上传插件实现。
  • 而后端,在jsp+Servlet时代,最常见的就是利用smartupload上传组件。而在SpringMvc时代,其提供了MultipartFile封装类它包含了文件的二进制流和文件相关属性(文件名、大小等)。所以在SpringBoot中也是使用此封装类进行文件上传的。
  • 上面说到,springmvc中是利用MultipartFile进行文件上传的。而MultipartFile是个接口类,它的实现类有CommonsMultipartFile和StandardMultipartFile。这里简单说明下:
    StandardMultipartFile:是基于j2ee自带的文件上传进行解析,即使用Servlet3.0提供的javax.servlet.http.Part上传方式。
    CommonsMultipartFile:是基于apache fileupload的解析。
  • 所以正常我们使用时,也是无需关系底层是以哪种方式进行文件上传处理的,SpringMvc会给我们做相应的转换的。
  • 链接:SpringBoot | 第十七章:web应用开发之文件上传

Servlet2.5 方式(原生apache fileupload方式):

  • 介绍一下使用到的几个核心类:
    ①DiskFileItemFactory – 设置磁盘空间,保存临时文件。只是一个工具类
    ②ServletFileUpload – 文件上传的核心类,此类接收 request,并解析
    ③ServletFileUpload.parseRequest(request); – List 解析 request
  • 流程:
    ①创建一个 DiskFileItemFactory 工厂类,并制定临时文件和大小
    ②创建 ServletFileUpload 核心类,接收临时文件,做请求的转换
    ③通过 ServletFileUpload 类转换原始请求,得到 FileItem 集合
    ④遍历集合中的各个元素并处理
    ⑤判断每个元素是否是普通表单项,如果是则按照普通表单项处理
    ⑥如果不是普通表单项,则是文件,通过处理的方式进行处理(上传)
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设定编码,可以获取中文文件名
        request.setCharacterEncoding("UTF-8");
        // 获取tomcat下的upload目录的路径
        String path = getServletContext().getRealPath("/upload");
        // 临时文件目录
        String tempPath = getServletContext().getRealPath("/temp");
        // 检查我们是否有文件上传请求
        // boolean isMultipart = ServletFileUpload.isMultipartContent(req);
        // 1、声明DiskFileItemFactory工厂类,用于在指定磁盘上设置一个临时目录
        DiskFileItemFactory disk = new DiskFileItemFactory(1024 * 10, new File(tempPath));
        // 2、声明ServletFileUpload,接收上面的临时文件。也可以默认值
        ServletFileUpload up = new ServletFileUpload(disk);
        // 3、解析request
        try {
            List<FileItem> list = up.parseRequest(request);
            if (list.size() > 0) {
                for (FileItem file : list) {
                    // 判断是否是普通的表单项
                    if (file.isFormField()) {
                        String fieldName = file.getFieldName();
                        // 中文乱码,此时还需要指定获取数据的编码方式
                        // String value = file.getString();
                        String value = file.getString("UTF-8");
                        System.out.println(fieldName + "=" + value);
                    } else { // 说明是一个文件
                        // 获取文件本身的名称
                        String fileName = file.getName();
                        System.out.println(file.getFieldName());
                        // 处理文件名称
                        fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
                        System.out.println("old Name : " + fileName);
                        // 修改名称
                        String extName = fileName.substring(fileName.lastIndexOf("."));
                        String newName = UUID.randomUUID().toString().replace("-", "") + extName;
                        // 保存新的名称,并写出到新文件中
                        file.write(new File(path + "/" + newName));
                        System.out.println("文件名是:" + fileName);
                        System.out.println("文件大小是:" + file.getSize());
                        file.delete();
                    }
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

Servlet3.0 方式(StandardMultipartFile方式):

  • 使用注解 @MultipartConfig 将一个 Servlet 标识为支持文件上传。Servlet3.0 将multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。
@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("上传文件...");
        // 设置编码
        request.setCharacterEncoding("UTF-8");
        // 获取普通表单项参数
        String uname = request.getParameter("uname");
        System.out.println(uname);
        // 上传文件
        // 得到part对象 request.getpart(name):name代表的是表单中file元素的name属性值
        Part part = request.getPart("myfile");
        // 得到文件存放的路径
        String path = request.getServletContext().getRealPath("/");
        // 得到文件名
        String fileName = part.getSubmittedFileName();
        // 上传
        part.write(path + fileName);
    }

}

SpringMVC方式(CommonsMultipartFile方式):

@Controller 
public class FileController { 
    @RequestMapping("/uploadFile") 
    public ModelAndView uploadFile(HttpServletRequest request){ 
        ModelAndView mv=new ModelAndView(); 
        mv.setViewName("result"); 
        MultipartHttpServletRequest mr=(MultipartHttpServletRequest) request; 
        MultipartFile multipartFile= mr.getFile("file"); 
        String path=request.getSession().getServletContext().getRealPath("upload"); 
        System.out.println(path); 
        if(null!=multipartFile&&!multipartFile.isEmpty()){ 
            String fileName=multipartFile.getOriginalFilename(); 
        try { 
            multipartFile.transferTo(new File(path,fileName)); 
            mv.addObject("msg", "文件上传成功!"); 
        } catch (Exception e) { 
            mv.addObject("msg", "上传失败!"); 
            e.printStackTrace(); 
        } 
        } 
        return mv; 
    } 
}

原生SmartUpload方式:

 		//实例化组件
        SmartUpload smartUpload = new SmartUpload();
        //初始化上传操作
        smartUpload.initialize(this.getServletConfig(), request, response);
        try {
            //上传准备
            smartUpload.upload();
            //对于普通数据,单纯到request对象是无法获取得到提交参数的。也是需要依赖smartUpload
            String password = smartUpload.getRequest().getParameter("password");
            System.out.println(password);
            //上传到uploadFile文件夹中
            smartUpload.save("uploadFile");
        } catch (SmartUploadException e) {
            e.printStackTrace();
        }

MultipartFile与CommonsMultipartFile与File的区别:

  • MultipartFile与CommonsMultipartFile:
    ①本质区别:MultipartFile 是接口, CommonsMultipartFile 是其实现类
    ②使用区别:CommonsMultipartFile 类型需要添加@RequestParam 参考博客
    ③建议使用: MultipartFile,原因一般情况都是使用接口,该接口可能会增加实现类,如此就不需要去修改代码中的类型;并且目前来说MultipartFile使用时不需要添加注解,比较方便。
  • MultipartFile与File:
    ①MultipartFile是spring类型,代表HTML中form data方式上传的文件,包含二进制数据+文件名称。

多种文件上传方式简介:

  • 多文件上传时和单文件上传时前端都是一个字段,因此没有区别,只不过多文件上传时弹出时选择多个文件就ok了。
@ResponseBody
    @RequestMapping(value = "uploadfiles", produces = "multipart/form-data;charset=UTF-8")
    public String uploadfile(MultipartHttpServletRequest request){
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        if (multipartResolver.isMultipart(request)) {
            //上传多个文件,一个字段中包含多个文件
            String projectPath = request.getSession().getServletContext().getRealPath("/");
            MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
            List<MultipartFile> fileSet = new LinkedList<>();
            for(Map.Entry<String, List<MultipartFile>> temp : multiFileMap.entrySet()){
                fileSet = temp.getValue();
            }

            for(MultipartFile temp : fileSet){
                File file2 = new File(projectPath+temp.getOriginalFilename());
                try {
                    temp.transferTo(file2);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return "";
    }
//多个文件的上传
    @PostMapping("/uploads")
    public String uploads(MultipartFile[] uploadFiles, HttpServletRequest request) {
        //1,对文件数组做判空操作
        if (uploadFiles == null || uploadFiles.length < 1) {
            return "文件不能为空";
        }
        //2,定义文件的存储路径,
        String realPath = request.getSession().getServletContext().getRealPath("/uploadFile/");
        File dir = new File(realPath);
        if (!dir.isDirectory()) {//文件目录不存在,就创建一个
            dir.mkdirs();
        }
        try {
            String filePathS = "";
            //3,遍历文件数组,一个个上传
            for (int i = 0; i < uploadFiles.length; i++) {
                MultipartFile uploadFile = uploadFiles[i];
                String filename = uploadFile.getOriginalFilename();
                //服务端保存的文件对象
                File fileServer = new File(dir, filename);
                System.out.println("file文件真实路径:" + fileServer.getAbsolutePath());
                //2,实现上传
                uploadFile.transferTo(fileServer);
                String filePath = request.getScheme() + "://" +
                        request.getServerName() + ":"
                        + request.getServerPort()
                        + "/uploadFile/" + filename;
                filePathS = filePathS + "\n" + filePath;
            }
            //4,返回可供访问的网络路径
            return filePathS;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上传失败";
    }
  • 多文件多字段上传
@ResponseBody
    @RequestMapping(value = "uploadfiles", produces = "multipart/form-data;charset=UTF-8")
    public String uploadfile(MultipartHttpServletRequest request){
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        if (multipartResolver.isMultipart(request)) {
            //上传多个文件,每个字段一个文件
            Iterator<String> fileNames = request.getFileNames();
            while (fileNames.hasNext()){
                // 取得上传文件
                String uploadName = fileNames.next();
                MultipartFile file = request.getFile(uploadName);
                if (file != null) {
                    String projectPath = request.getSession().getServletContext().getRealPath("/");
                    String originalFilename = file.getOriginalFilename();
                    String tmpFile = projectPath + System.currentTimeMillis() + "_" + originalFilename;
                    File targetFile = new File(tmpFile);
                    try {
                        file.transferTo(targetFile);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return "";
    }

大文件上传,秒传、断点续传、分片上传:

  • 什么是秒传:
    ①通俗的说,你把要上传的东西上传,服务器会先做MD5校验,如果服务器上有一样的东西,它就直接给你个新地址,其实你下载的都是服务器上的同一个文件,想要不秒传,其实只要让MD5改变,就是对文件本身做一下修改(改名字不行),例如一个文本文件,你多加几个字,MD5就变了,就不会秒传了.
  • 什么是分片上传:
    ①分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。
    ②分片上传的场景:
    <1>大文件上传
    <2>网络环境环境不好,存在需要重传风险的场景
  • 什么是断点续传:
    ①断点续传是在下载或上传时,将下载或上传任务(一个文件或一个压缩包)人为的划分为几个部分,每一个部分采用一个线程进行上传或下载,如果碰到网络故障,可以从已经上传或下载的部分开始继续上传或者下载未完成的部分,而没有必要从头开始上传或者下载。本文的断点续传主要是针对断点上传场景。
    ②应用场景:
    <1>断点续传可以看成是分片上传的一个衍生,因此可以使用分片上传的场景,都可以使用断点续传。
  • 链接:大文件上传:秒传、断点续传、分片上传

上传文件后的处理方式:

  • 通过流的方式直接处理
  • 采用file.transferTo()方法

文件上传原理:

  • 步骤:
    ①读取 http body 部分
    ②根据 boundary 分析出分隔符特征(这个串是唯一的,不会与body内其他数据冲突)
    ③根据实际分隔符分段获取 body 内容
    ④遍历分段内容根据 Content-Disposition 特征获取其中值
    ⑤根据值中 filename 或 name 区分是否是包含二进制流还是表单数据的 k-v
    ⑥根据 filename 获取原始文件名
    ⑦从连续 两个 newline 字符串为起始至当前分段完毕,按照二进制流读取上传文件流信息。
    ⑧完成后即有:
    <1>原始文件名信息
    <2>原始文件类型信息
    <3>全部文件流信息
  • 文件上传为什么要用 multipart/form-data不使用旧有的application/x-www-form-urlencoded?
    ①因为此类型不适合用于传输大型二进制数据或者包含非ASCII字符的数据。平常我们使用这个类型都是把表单数据使用url编码后传送给后端,二进制文件当然没办法一起编码进去了。所以multipart/form-data就诞生了,专门用于有效的传输文件。
  • 可以用 application/json吗?
    ①无论你用什么都可以传,只不过会要综合考虑一些因素的话,multipart/form-data更好。例如我们知道了文件是以二进制的形式存在,application/json 是以文本形式进行传输,那么某种意义上我们确实可以将文件转成例如文本形式的 Base64 形式。但是呢,你转成这样的形式,后端也需要按照你这样传输的形式,做特殊的解析。并且文本在传输过程中是相比二进制效率低的,那么对于我们动辄几十M几百M的文件来说是速度是更慢的。

Java下载文件的几种方式:

  • 简介:
    Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。
    ②格式说明: content-disposition = “Content-Disposition” “:” disposition-type *( “;” disposition-parm )  
    ③字段说明:Content-Disposition为属性名disposition-type是以什么方式下载,如attachment为以附件方式下载disposition-parm为默认保存时的文件名服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器中显示,如果需要提示用户保存,就要利用Content-Disposition进行一下处理,关键在于一定要加上attachment:复制代码 代码如下:
Response.AppendHeader("Content-Disposition","attachment;filename=FileName.txt");
  • 以流的方式下载.:
public HttpServletResponse download(String path, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
 
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }
  • 下载本地文件:
public void downloadLocal(HttpServletResponse response) throws FileNotFoundException {
        // 下载本地文件
        String fileName = "Operator.doc".toString(); // 文件的默认保存名
        // 读到流中
        InputStream inStream = new FileInputStream("c:/Operator.doc");// 文件的存放路径
        // 设置输出的格式
        response.reset();
        response.setContentType("bin");
        response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        // 循环取出流中的数据
        byte[] b = new byte[100];
        int len;
        try {
            while ((len = inStream.read(b)) > 0)
                response.getOutputStream().write(b, 0, len);
            inStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 下载网络文件:
public void downloadNet(HttpServletResponse response) throws MalformedURLException {
        // 下载网络文件
        int bytesum = 0;
        int byteread = 0;
 
        URL url = new URL("windine.blogdriver.com/logo.gif");
 
        try {
            URLConnection conn = url.openConnection();
            InputStream inStream = conn.getInputStream();
            FileOutputStream fs = new FileOutputStream("c:/abc.gif");
 
            byte[] buffer = new byte[1204];
            int length;
            while ((byteread = inStream.read(buffer)) != -1) {
                bytesum += byteread;
                System.out.println(bytesum);
                fs.write(buffer, 0, byteread);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 支持在线打开的方式:
public void downLoad(String filePath, HttpServletResponse response, boolean isOnLine) throws Exception {
        File f = new File(filePath);
        if (!f.exists()) {
            response.sendError(404, "File not found!");
            return;
        }
        BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
        byte[] buf = new byte[1024];
        int len = 0;
 
        response.reset(); // 非常重要
        if (isOnLine) { // 在线打开方式
            URL u = new URL("file:///" + filePath);
            response.setContentType(u.openConnection().getContentType());
            response.setHeader("Content-Disposition", "inline; filename=" + f.getName());
            // 文件名应该编码成UTF-8
        } else { // 纯下载方式
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment; filename=" + f.getName());
        }
        OutputStream out = response.getOutputStream();
        while ((len = br.read(buf)) > 0)
            out.write(buf, 0, len);
        br.close();
        out.close();
    }

Fastdfs文件服务器

文件服务器简介:

  • ftp:可设密码文件安全性高(若设密码程序访问麻烦)、可断点续传、不可扩容、无容灾
  • HDFS:适用于大文件存储、云计算、不太适合单纯小文件存储(效率不高)
  • TFS:出自于淘宝,适用于海量小于1M文件、使用相对麻烦、文档相对少
  • GlusterFS:功能强大灵活、适合大文件、支持多种数据类型、使用麻烦、对硬件要求高、至少两个节点、中文资料少
  • mogileFS:与FastDFS架构比较像、FastDFS参考mogileFS,FastDFS比mogileFS效率高
  • FastDFS:出自于淘宝,适用于海量小文件(建议范围:4KB < file_size<500MB)、使用相对简单、小文件存储网上大多推荐使用FastDFS

FastDFS:

  • 优点
    1)降低了系统的复杂度,处理效率更高
    2)支持在线扩容机制,增强系统的可扩展性
    3)实现了软RAID,增强系统的并发处理能力及数据容错恢复能力
    4)支持主从文件,支持自定义扩展名
    5)主备Tracker服务,增强系统的可用性
  • 缺点
    1)不支持断点续传,不适合大文件存储
    2)不支持POSIX(可移植操作系统接口)通用接口访问,通用性较低
    3)对跨公网的文件同步,存在较大延迟,需要应用做相应的容错策略
    4)同步机制不支持文件正确性校验,降低了系统的可用性
    5)通过API下载,存在单点的性能瓶颈
    6)不直接提供权限控制,需自己实现
  • 总结:相比其他常见的开源分布式文件系统,FastDFS不够完美,但比较合适小文件的需求。

分布式文件系统(HDFS和FastDFS):

  • FastDFS客户端底层连接服务端使用的是Socket,本身速度就要快很多。
  • HDFS在做删除测试时,明显较慢的地方是在创建到服务端的连接上,实际删除文件的速度很快。由于每次测试都需要先创建到服务端的连接,HDFS在这块消耗较大,在实际场景下,差距应该没有这么大。
    ①链接:springboot上传下载文件(3)–java api 操作HDFS集群+集群配置
  • 两者的适用场景确有不同,FastDFS更适合小文件的高效存取,而HDFS更适合超大文件上传后使用Mapreduce去做大数据处理。

四种搭建文件服务器的方式:

  • 第一种:Nginx自带的,autoIndex.
    优点:配置快,开发速度最快,用起来不方便。
    缺点:没有密码验证,信息泄露,每个人都可以访问。
  • 第二种、安装BasicAuth 登录验证
    优点:安全性高
    缺点:自己用,添加用户的方式太麻烦了。
    严格来说,第一种、第二种不能叫做文件服务器,只能下载,不能实现文件的上传。
  • 第三种 Nginx+Lua 搭建文件服务器,可以上传下载
    优点:多用户,文件上传,下载。
    缺点:配置复杂。(设计lua元表,闭包,数据链接)不过 代码我给你了。
    该方案不适合用于工程项目
  • 第四种 分布式文件系统
    优点:基本上公司都是这么干的
    缺点:配置更加的复杂(FastDFS,SpringBoot,MySQL,Vue(thymeleaf))

ftp服务器和文件服务器有什么区别和联系?

  • ftp服务器只是说把这个服务器做成通过ftp协议共享文件下载的,而文件服务器就概念比较模糊了,就一台机子,放着公司所有人公用的文件,然后把这些文件共享了,不用ftp模式,大家也都可以下载,这样也叫一种文件服务器,
  • 都是供别人下载文件的,一般的区别就是,在局域网内用文件共享就可以了,在外网,也就是互联网上用ftp的多

视频上传与下载

流媒体:

  • 流媒体(streaming media)是指将一连串的媒体数据压缩后,经过网上分段发送数据,在网上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如果不使用此技术,就必须在使用前下载整个媒体文件。流式传输可传送现场影音或预存于服务器上的影片,当观看者在收看这些影音文件时,影音数据在送达观看者的计算机后立即由特定播放软件播放。

ffmpeg:

  • FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。
  • FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OSX等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer项目,而且当前FFmpeg也是放在MPlayer项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"。 [1] FFmpeg编码库可以使用GPU加速。
  • 视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播放该文件。
  • 多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。
  • ffmpeg视频采集功能非常强大,不仅可以采集视频采集卡或USB摄像头的图像,还可以进行屏幕录制,同时还支持以RTP方式将视频流传送给支持RTSP的流媒体服务器,支持直播应用。
  • ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
  • 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
  • 链接:Java实现视频网站的视频上传、视频转码、及视频播放功能(ffmpeg)

Red5服务器搭建:

  • 流媒体服务器是通过建立发布点来发布流媒体内容和管理用户连接的。流媒体服务器能够发布从视频采集卡或摄像机等设备中传来的实况流,也可以发布事先存储的流媒体文件,并且发布实况流和流媒体文件的结合体。一个媒体流可以由一个媒体文件构成,也可以由多个媒体文件组合而成,还可以由一个媒体文件目录组成。
  • Flash Media Server,简称 FMS,是 Flash 大家庭里的一员,被称为是目前开发 Web 音视频应用程序(比如,视频聊天室、视频会议系统、播客系统、音视频留言等等)的最方便最快捷的解决方案。也在 web 应用程序开发上有着越来越广泛的应用。当然 FMS 这种优良功能并不是免费提供给广大用户的,几千美金每个点的价格让很多开发人员望而却步。于是,大家开始尝试寻找一种更合适的解决方案,开源的 Red5 便成为了人们的新宠。
  • Red5 是一个采用 Java 开发的开源的 Flash 流媒体服务器,功能上与 FMS 类似。它支持:把音频(MP3)和视频(FLV)转换成播放流;录制客户端播放流(只支持 FLV);共享对象;现场直播流发布;远程调用。Red5 使用 RSTP 作为流媒体传输协议,包括在线录制,Flash 流媒体播放,在线聊天,视频会议等一些基本功能。国内外基于 Red5 的流媒体应用产品也在不断推广。
  • Red 5 支持:
    ①把音频(MP3)和视频(FLV, F4V, MP4, 3GP)转换成播放流;
    ②录制客户端播放流, 把摄像头,麦克风等传入的音频视频录制保存到服务器;
    ③共享对象;
    ④现场直播流发布;
    ⑤远程调用;
    ⑥协议:RTMP, RTMPT, RTMPS, and RTMPE。
  • 链接:Red5服务器搭建(实现在线直播,流媒体视频播放)

jwplayer +ffmpeg+red5 整合:

  • 这种方案对应的基本架构如图所示,包含三个组成部分:摄像头、服务器部分和客户端部分:
    在这里插入图片描述
  • 摄像头:摄像头可以提供实时的视频流,然而要访问摄像头的实时数据,通常需要知道摄像头对应的RTSP访问地址。
  • 服务器端:服务器端由“red5”和“ffmpeg”两部分构成;其中ffmpeg用于将RTSP的视频流转码成为RTMP的视频流,red5是一个流媒体服务器器,用于提供视频流的发布和访问服务。
  • 客户端:客户端使用的播放器是“jwplayer”,这是一个在网页上使用的Flash播放器,它支持的流媒体协议是“RTMP”,只需要在JS代码中指定合适的“file”属性和“streamer”属性,即可播放对应的RTMP视频流。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值