当前位置: 移动技术网 > IT编程>开发语言>Java > 自己动手写一个java版简单云相册

自己动手写一个java版简单云相册

2019年07月22日  | 移动技术网IT编程  | 我要评论

动手写一个java版简单云相册,实现的功能是:
用户可以一次上传一个至多个文件。
用户可以下载其他人上传的图片。
用户可以查看其他所有人的图片。
用户只能删除通过自己ip上传的图片。

用到的技术:
文件上传下载、设计模式、dom4j、xpath等。

先看下2个页面:

源代码:

web.xml:

<?xml version="1.0" encoding="utf-8"?>
<web-app version="3.0" 
  xmlns="http://java.sun.com/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" 
  xsi:schemalocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 <display-name></display-name>
 <servlet>
  <servlet-name>uploadservlet</servlet-name>
  <servlet-class>cn.hncu.servlets.uploadservlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>cloudphotoservlet</servlet-name>
  <servlet-class>cn.hncu.servlets.cloudphotoservlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>downservlet</servlet-name>
  <servlet-class>cn.hncu.servlets.downservlet</servlet-class>
 </servlet>
 <servlet>
  <servlet-name>delservlet</servlet-name>
  <servlet-class>cn.hncu.servlets.delservlet</servlet-class>
 </servlet>



 <servlet-mapping>
  <servlet-name>uploadservlet</servlet-name>
  <url-pattern>/upload</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>cloudphotoservlet</servlet-name>
  <url-pattern>/cloudphoto</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>downservlet</servlet-name>
  <url-pattern>/servlet/downservlet</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>delservlet</servlet-name>
  <url-pattern>/servlet/delservlet</url-pattern>
 </servlet-mapping>  
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
</web-app>

index.jsp:

<%@ page language="java" import="java.util.*" pageencoding="utf-8"%>

<!doctype html public "-//w3c//dtd html 4.01 transitional//en">
<html>
 <head>
  <title>chx云相册</title>
  <script type="text/javascript">
    function delfile(input){
      table = input.parentelement.parentelement.parentelement;//table.nodename tbody

      table.removechild(input.parentelement.parentelement);
    }
    var t=1;
    function addfile(input){
      tr = input.parentelement.parentelement;
      //alert(tr.nodename);
      var str = "<td>选择文件:</td>"+
        "<td> <input type='file' name='file"+t+"'> </td> "+
        "<td>文件说明:</td>"+
        "<td> <input type='text' name='text"+t+"'> </td> "+
        "<td> <input type='button' value='删除文件' onclick='delfile(this)'> </td>";
      tr.insertadjacenthtml("beforebegin",str);
    }

    function move(){
      window.location.href="/myphoto/cloudphoto";
    }
  </script>

  <style type="text/css">
    #font{
      color:red;
    }

  </style>
 </head>

 <body>
  <h1><font id="font">相册上传:</font></h1>
  <form action="/myphoto/upload" method="post" enctype="multipart/form-data">
    <table border="1px;double;#ff0000">
      <tr>
        <td>选择文件:</td>
        <td> <input type="file" name="file1"> </td> 
        <td>文件说明:</td>
        <td> <input type="text" name="text1"> </td> 
        <td> <input type="button" value="删 除 文 件" onclick="delfile(this)"> </td>
      </tr>
      <tr>
        <td colspan=2> <input type="submit" value="上 传 文 件"> </td>
        <td colspan=3> <input type="button" value="添 加 文 件" onclick="addfile(this)"> </td>
      </tr>
    </table>
  </form>
  <form action="/myphoto/cloudphoto" method="post" enctype="multipart/form-data">
    <table border="1px;double;#ff0000">
      <tr>
        <td colspan=5><input type="submit" value="进 入 云 相 册" onclick="move()"></td>
      </tr>
    </table>
  </form>
 </body>
</html>

photo.xml:

<?xml version="1.0" encoding="utf-8"?>
<photos>

</photos>

myutils.java:

package cn.hncu.utils;

import java.text.simpledateformat;
import java.util.date;
import java.util.uuid;

public class myutils {

  /**
   * @return 获取uuid
   */
  public static string getuuid(){
    return uuid.randomuuid().tostring().replace("-", "");
  }

  /**
   * @param uuid
   * @return 通过uuid,获得打散后的路径
   */
  public static string getdir(string uuid){
    string dir1 = integer.tohexstring( uuid.hashcode() & 0xf );
    string dir2 = integer.tohexstring( (uuid.hashcode() & 0xf0)>>4 );
    return "/"+dir1+"/"+dir2;
  }

  //日期时间格式
  private static simpledateformat sdf = new simpledateformat("yyyy年mm月dd日 hh:mm:ss");
  /**
   * @return 返回的是上传的时候的日期时间
   */
  public static string getcurrentdatetime(){
    return sdf.format(new date());
  }

}

dom4jfactory.java:

package cn.hncu.utils;

import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.unsupportedencodingexception;

import org.dom4j.document;
import org.dom4j.documentexception;
import org.dom4j.element;
import org.dom4j.node;
import org.dom4j.io.saxreader;
import org.dom4j.io.xmlwriter;

public class dom4jfactory {
  private static document dom=null;
  private static string path;
  //静态块!只会运行一次!特点是在类加载的时候就执行
  static{
    try {
      saxreader sax = new saxreader();
      //因为我们的资源已经从myelipse中发布到tomcat服务器中了,所以跟原来的纯java项目不一样了。
      //利用当前类找到它的类加载器,然后通过该类加载器再去获得资源路径
      path = dom4jfactory.class.getclassloader().getresource("photo.xml").getpath();
      //getclassloader()返回:加载此对象所表示的类或接口的类加载器
      //public url getresource(string name)返回:读取资源的 url 对象;如果找不到该资源,或者调用者没有足够的权限获取该资源,则返回 null。
      //此方法首先搜索资源的父类加载器;如果父类加载器为 null,则搜索的路径就是虚拟机的内置类加载器的路径。
      //public string getpath()获取此 url 的路径部分。 
      system.out.println(path);
      dom = sax.read(new fileinputstream(path));
    } catch (filenotfoundexception e) {
      throw new runtimeexception(e);
    } catch (documentexception e) {
      throw new runtimeexception(e);
    }
  }

  /**
   * @return 获取相册的document
   */
  public static document getdocument(){
    return dom;
  }

  /**
   * 进行photo.xml的保存,保存到本地
   */
  public static boolean save(){
    try {
      xmlwriter w = new xmlwriter(new fileoutputstream(path));
      w.write(dom);
      w.close();
      return true;
    } catch (unsupportedencodingexception e) {
      return false;
    } catch (filenotfoundexception e) {
      return false;
    } catch (ioexception e) {
      return false;
    }
  }

  public static boolean del(string uuid){
    node node = dom.selectsinglenode("[@uuid='"+uuid+"']");
    if(node==null){
      return false;
    }
    node.getparent().remove(node);
    return true;
  }


  /**
   * 测试用
   * @param args
   */
  public static void main(string[] args){
    system.out.println( getdocument() );
  }
}

photomodel.java-值对象

package cn.hncu.domain;
/**
 * 值对象封装
 * @author 陈浩翔
 * 2016-7-24
 */
public class photomodel {

  private string uuid;//uuid
  private string realname="";//图片真实文件名(上传时的文件名)
  private string ext;//后缀名
  private string dir;//打散后的路径
  private string datetime;//上传文件的时间
  private string ip;//上传者的ip
  private string desc;//文件的说明
  public string getuuid() {
    return uuid;
  }
  public void setuuid(string uuid) {
    this.uuid = uuid;
  }
  public string getrealname() {
    return realname;
  }
  public void setrealname(string realname) {
    this.realname = realname;
  }
  public string getext() {
    return ext;
  }
  public void setext(string ext) {
    this.ext = ext;
  }
  public string getdir() {
    return dir;
  }
  public void setdir(string dir) {
    this.dir = dir;
  }
  public string getdatetime() {
    return datetime;
  }
  public void setdatetime(string datetime) {
    this.datetime = datetime;
  }
  public string getip() {
    return ip;
  }
  public void setip(string ip) {
    this.ip = ip;
  }
  public string getdesc() {
    return desc;
  }
  public void setdesc(string desc) {
    this.desc = desc;
  }
  @override
  public string tostring() {
    return "photomodel [uuid=" + uuid + ", realname=" + realname + ", ext="
        + ext + ", dir=" + dir + ", datetime=" + datetime + ", ip="
        + ip + ", desc=" + desc + "]";
  }

}

photodao.java:

package cn.hncu.photodao.dao;

import java.util.list;

import cn.hncu.domain.photomodel;

public interface photodao {
  /**
   * @param photo
   * @return 数据的保存
   */
  public boolean save(photomodel photo);

  /**
   * @return 返回所所有的图片信息
   */
  public list<photomodel> getall();

  /**
   * @param uuid
   * @return 通过uuid 查找那个被封装的值对象
   */
  public photomodel getsinglebyuuid(string uuid);


  /**
   * @param uuid
   * @return 通过uuid删除photos.xml中该图片的信息
   */
  public boolean deletexml(string uuid);

  /**
   * @param dir
   * @return 通过路径删除服务器磁盘中该图片的信息
   */
  public boolean deletefile(string pathfilename);
}

photoserimpl.java:

package cn.hncu.photodao.impl;

import java.io.file;
import java.util.arraylist;
import java.util.iterator;
import java.util.list;

import org.dom4j.document;
import org.dom4j.element;
import org.dom4j.node;

import cn.hncu.domain.photomodel;
import cn.hncu.photodao.dao.photodao;
import cn.hncu.utils.dom4jfactory;

public class photoserimpl implements photodao{

  @override
  public boolean save(photomodel photo) {
    document dom = dom4jfactory.getdocument();

    element root = dom.getrootelement();
    //添加属性
    element p = root.addelement("photo");
    p.addattribute("uuid", photo.getuuid());
    p.addattribute("realname", photo.getrealname());
    p.addattribute("datetime", photo.getdatetime());
    p.addattribute("ip", photo.getip());
    p.addattribute("ext", photo.getext());
    p.addattribute("dir", photo.getdir());
    p.addattribute("desc", photo.getdesc());
    return dom4jfactory.save();
  }

  @override
  public list<photomodel> getall() {
    list<photomodel> list = new arraylist<photomodel>();
    document dom = dom4jfactory.getdocument();
    element root = dom.getrootelement();
    iterator<element> it = root.elementiterator("photo");
    //通过dom4j获得photo元素的迭代器,也可以通过xpath来找到所有的 photo
    //list<node> lists = dom.selectnodes("//photo[@uuid]");
    //iterator<node> it = lists.iterator();
    while(it.hasnext()){
      element e = it.next();
      photomodel photo = new photomodel();
      photo.setuuid(e.attributevalue("uuid"));
      photo.setrealname(e.attributevalue("realname"));
      photo.setdatetime(e.attributevalue("datetime"));
      photo.setext(e.attributevalue("ext"));
      photo.setip(e.attributevalue("ip"));
      photo.setdir(e.attributevalue("dir"));
      photo.setdesc(e.attributevalue("desc"));
      list.add(photo);
    }
    return list;
  }

  @override
  public photomodel getsinglebyuuid(string uuid) {
    list<photomodel> photos=getall();
    for(photomodel photo:photos){
      if(photo.getuuid().equals(uuid)){
        return photo;
      }
    }
    return null;
  }

  @override
  public boolean deletexml(string uuid) {
    document dom = dom4jfactory.getdocument();
    element e = (element) dom.selectsinglenode("//photo[@uuid='"+uuid.trim()+"']");
    return e.getparent().remove(e);
  }

  @override
  public boolean deletefile(string pathfilename) {
    try {
      file file = new file(pathfilename);
      if(file.exists()){
        file.delete();
      }
      return true;
    } catch (exception e) {
      return false;
    }
  }
}

photodaofactory.java:

package cn.hncu.photodao.factory;

import cn.hncu.photodao.impl.photoserimpl;

/**
 * 工厂方法
 * @author 陈浩翔
 * 2016-7-24
 */
public class photodaofactory {
  public static photoserimpl getphotodao(){
    return new photoserimpl();
  }
}

上传-uploadservlet.java:

package cn.hncu.servlets;

import java.io.file;
import java.io.ioexception;
import java.io.printwriter;
import java.util.list;

import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import org.apache.commons.fileupload.fileitem;
import org.apache.commons.fileupload.fileuploadexception;
import org.apache.commons.fileupload.disk.diskfileitemfactory;
import org.apache.commons.fileupload.servlet.servletfileupload;

import cn.hncu.domain.photomodel;
import cn.hncu.photodao.dao.photodao;
import cn.hncu.photodao.factory.photodaofactory;
import cn.hncu.utils.dom4jfactory;
import cn.hncu.utils.myutils;

public class uploadservlet extends httpservlet {
  public void doget(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    response.setcontenttype("text/html;charset=utf-8");
    response.getwriter().print("<h1>很抱歉,本页面不支持get方式访问!!!</h1>");
    response.getwriter().print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
  }
  public void dopost(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    response.setcontenttype("text/html;charset=utf-8");
    final printwriter out = response.getwriter();

    //防黑-非multipart表单提交
    //使用上传工具的方式
    boolean boo = servletfileupload.ismultipartcontent(request);
    if(!boo){
      out.print("<h1>不支持普通表单的提交方式!</h1>");
      return;
    }

    file file = new file("d:/photocache");
    if(!file.exists()){
      file.mkdir();
    }

    diskfileitemfactory fifactory = new diskfileitemfactory(1024*10,file);

    servletfileupload upload = new servletfileupload(fifactory);
    upload.setheaderencoding("utf-8");//设置文件名编码
    string path = getservletcontext().getrealpath("/photos");


    fileitem fi = null;
    try {
      list<fileitem> list = upload.parserequest(request);
      photomodel photo = new photomodel();//数据封装---需要7个属性
      photo.setrealname("");
      int cont=0;
      for(fileitem f:list){
        if(cont!=0 && cont%2==0 && !photo.getrealname().equals("")){
          photo = new photomodel();//重新数据封装
        }
        fi=f;
        if(fi.isformfield()){//普通表单组件
          //得到文件说明
          string desc = fi.getstring("utf-8");
          photo.setdesc(desc);//#1
        }else{

          //防黑3-如果在file组件中不选择文件
          if(fi.getsize()==0){
            photo.setrealname("");
            cont++;
            continue;
          }
          string filename = fi.getname();
          filename = filename.substring( filename.lastindexof("\\")+1);//真实文件名
          photo.setrealname(filename);//#2
          string ext = filename.substring(filename.lastindexof("."));//扩展名
          photo.setext(ext);//#3
          photo.setdatetime(myutils.getcurrentdatetime());//#4
          photo.setip( request.getremoteaddr() );//#5
          string uuid = myutils.getuuid();
          photo.setuuid(uuid);//#6
          photo.setdir( myutils.getdir(uuid) );//#7

          //打散目录
          file dfile = new file(path+photo.getdir());
          if(!dfile.exists()){
            dfile.mkdirs();
          }

          fi.write(new file(path+photo.getdir()+"/"+photo.getuuid()+photo.getext()));


        }

        cont++;

        if(cont%2==0 && !photo.getrealname().equals("")){
          photodao dao = photodaofactory.getphotodao();
          boo = dao.save(photo);
          //存入磁盘-法二:fileutils.copyinputstreamtofile(in, new file(filename2));//※2※ 把图片文件存储到服务器硬盘
          photo = new photomodel();//重新数据封装
        }
      }
    } catch (fileuploadexception e) {
      e.printstacktrace();
    } catch (exception e) {
      e.printstacktrace();
    }finally{
      if(fi!=null){
        fi.delete();
      }
      if(dom4jfactory.save()){
        out.print("<h1>上传成功!</h1>");
        out.print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
      }else{
        out.print("<h1>上传失败!</h1>");
        out.print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
      }
    }
  }
}

显示所有文件-cloudphotoservlet.java

package cn.hncu.servlets;

import java.io.ioexception;
import java.io.printwriter;
import java.util.list;

import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import cn.hncu.domain.photomodel;
import cn.hncu.photodao.dao.photodao;
import cn.hncu.photodao.factory.photodaofactory;

public class cloudphotoservlet extends httpservlet {
  public void doget(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    string pwd = (string) request.getparameter("pwd");
    if ("chx".equals(pwd)) {
      dopost(request, response);
    } else {
      response.setcontenttype("text/html;charset=utf-8");
      response.getwriter().print("<h1>很抱歉,你没有权限访问!!!</h1>");
    }
  }

  public void dopost(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {

    response.setcontenttype("text/html;charset=utf-8");
    printwriter out = response.getwriter();
    out.println("<!doctype html public \"-//w3c//dtd html 4.01 transitional//en\">");
    out.println("<html>");
    out.println(" <head><title>chx云相册</title></head>");
    out.println(" <body>");

    out.println("<table border='1px;double;#ff0000'>");
    out.println("<tr>");
    out.println("<td>文件名</td>");
    out.println("<td>上传时间");
    out.println("<td>文件</td>");
    out.println("<td>文件说明</td>");
    out.println("<td>操作</td> ");
    out.println("</tr>");

    string tdwh = "style='width:200px; height:200px;'";

    // 显示所有图片
    photodao dao = photodaofactory.getphotodao();
    list<photomodel> photos = dao.getall();
    for (photomodel photo : photos) {
      string filename = photo.getrealname();
      string time = photo.getdatetime();

      // 输出图片
      string path = request.getcontextpath() + "/photos/"
          + photo.getdir() + "/" + photo.getuuid() + photo.getext();
      // system.out.println(path);
      // /myphoto/photos//7/c/a1237a48a6aa451cb22fa78b15bafcea.jpg
      string img = "<a href='" + path + "'><img src='" + path + "'/></a>";
      string desc = photo.getdesc();

      string delstr = "<a href='/myphoto/servlet/delservlet?uuid="
          + photo.getuuid() + "'>删除</a>";
      string downstr = "<a href='/myphoto/servlet/downservlet?uuid="
          + photo.getuuid() + "'>下载</a>";

      out.println("<tr>");
      out.println("<td " + tdwh + "> " + filename + " </td>");
      out.println("<td " + tdwh + ">" + time + "</td>");
      out.println("<td " + tdwh + ">" + img + "</td>");
      out.println("<td " + tdwh + ">" + desc + "</td>");
      out.println("<td " + tdwh + ">" + delstr + " " + downstr
          + "</td>");
      out.println("</tr>");
    }

    out.println("<tr>");
    out.println("</tr>");

    out.println("</table>");

    out.println(" </body>");
    out.println("</html>");
    out.flush();
    out.close();
  }

}

删除文件-delservlet.java

package cn.hncu.servlets;

import java.io.ioexception;
import java.io.printwriter;

import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import cn.hncu.domain.photomodel;
import cn.hncu.photodao.dao.photodao;
import cn.hncu.photodao.factory.photodaofactory;

public class delservlet extends httpservlet {

  //注入
  private photodao dao = photodaofactory.getphotodao();
  public void doget(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    dopost(request, response);
  }


  public void dopost(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    string uuid = request.getparameter("uuid");
    string ip = request.getremoteaddr();
    response.setcontenttype("text/html;charset=utf-8");

    printwriter out = response.getwriter();

    photomodel photo = dao.getsinglebyuuid(uuid);

    if(photo!=null){
      if(!photo.getip().equals(ip)){
        out.print("<h1>你没有权限删除这个文件!!!</h1>");
        out.print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
        return ;
      }

      //1.删除数据库中的信息
      boolean boo = dao.deletexml(uuid);

      if(boo){
        string filename = "photos/"+photo.getdir()+"/"+photo.getuuid()+photo.getext();
        string pathfilename = getservletcontext().getrealpath(filename);
        if(dao.deletefile(pathfilename)){
          //重定向到相册页面
          response.sendredirect("/myphoto/cloudphoto?pwd=chx");
        }else{
          out.print("<h1>无法从服务器中删除,文件正在被占用!!!</h1>");
          out.print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
        }
      }else{
        out.print("<h1>该文件已经不存在!!!</h1>");
        out.print("<a href='javascript:history.go(-1)'>返回上一页</a> ");
      }
    }
  }
}

下载文件-downservlet.java

package cn.hncu.servlets;

import java.io.fileinputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.outputstream;
import java.net.urlencoder;

import javax.servlet.servletexception;
import javax.servlet.http.httpservlet;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import cn.hncu.domain.photomodel;
import cn.hncu.photodao.dao.photodao;
import cn.hncu.photodao.factory.photodaofactory;

public class downservlet extends httpservlet {
  private photodao dao = photodaofactory.getphotodao();

  public void doget(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {
    dopost(request, response);
  }

  public void dopost(httpservletrequest request, httpservletresponse response)
      throws servletexception, ioexception {

    string uuid = request.getparameter("uuid");
    system.out.println(uuid);
    photomodel photo = dao.getsinglebyuuid(uuid);
    system.out.println(photo);
    if(photo!=null){
      //设置响应头--内容接收程序--浏览器看到这个响应头,就会把它认为的下载程序打开
      //(如果识别迅雷那么就会自动打开迅雷,如果没有则会打开一个“文件另存为”的对话框)
      response.setcontenttype("application/force-download");

      string realname = photo.getrealname();

      string agent = request.getheader("user-agent");
      system.out.println(agent);
      if(agent.indexof("mozilla")!=-1){//火狐浏览器
        response.setheader("content-disposition", "attachment;filename="+ new string(realname.getbytes("gb2312"),"iso-8859-1"));
      }else{
        //解决中文乱码问题(只要用下面一句对文件名进行编码就行了)
        realname = urlencoder.encode(realname, "utf-8");//使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式。
        response.setheader("content-disposition", "attachment;filename=\""+realname+"\"");
        //注意:“cttachment;”不能少,否则浏览器会直接在新窗口中打开
      }

      string filename = "photos/" + photo.getdir()+"/"+photo.getuuid()+photo.getext();
      string pathfilename = getservletcontext().getrealpath(filename);

      inputstream in = new fileinputstream(pathfilename);
      outputstream out = response.getoutputstream();

      byte buf[] = new byte[2048];
      int len=0;
      while( (len=in.read(buf))!=-1 ){
        out.write(buf, 0, len);
      }
      out.close();
      in.close();
    }else{
      response.setcontenttype("text/html;charset=utf-8");
      response.getwriter().println("<h1>该文件已经被删除了</h1>");
    }
  }

}

演示结果

这个我就不演示啦,图片在前面也有,所有的源码我都给了。有兴趣的可以自己取改进一下咯。
其实这个还能上传其他任意类型文件哦,因为我们没有防护后缀名的,而且我们是用字符流传输,全都不会失真(可以当云盘来处理了~~)!!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网