文件上传方案

  • 基于Ajax+HTML的文件上传方案
    • 文件上传-二进制数据
    • 通过Ajax发送二进制流数据
      • 前端代码编写
    • 文件上传-后端处理
      • 后端代码编写
      • 消息响应
  • 文件服务器-分服务器文件上传
    • 后端开发-服务器职责
    • 将Tomcat服务器作为文件服务器
      • 制作并启动文件服务器
      • SSM项目:添加跨服务文件上传依赖
      • 跨服务器文件上传:前端代码编写
      • 跨服务器文件上传:后端代码编写
  • 补充:基于Axios+Element UI文件上传方案
    • 后端代码
    • Element UI组件使用与Axios数据请求
      • el-upload上传组件
      • el-upload事件处理
      • Axios发送文件上传请求

JavaWeb后端服务开发过程中,有对文件上传服务的需求。

在之前的《Axios+SSM上传和获取图片》中,提供了图片上传和显示的解决方案,但是对于数据量更大的文件,虽然例如MySQL数据库提供了用于存储二进制文件的Blob字段类型,但是,在文件读写过程中,可能会造成数据表或者二进制文件损坏的情况。

因此,更加实用的方案是:将文件上传到Tomcat服务器所在主机或者远程主机的硬盘上存储,而将文件上传记录(即:文件链接/地址)以字符串形似存储到数据库中;等到用户通过浏览器页面,需要浏览文件时,再通过数据库中记录的文件链接信息,从本地或者远程主机的硬盘读取文件,将其响应给浏览器客户端展示/下载。

基于Ajax+HTML的文件上传方案

文件上传-二进制数据

在浏览器页面中实现文件选择功能,可以使用input type=file解决。
    需要上传的数据中,不建议携带除了上传资源以外的数据。但通常可以是,普通数据(用户名/id等)+二进制文件数据(二进制文件数据通过二进制流的方式发送给服务器)。

通过Ajax发送二进制流数据

发送二进制流数据,仍然是通过FormData对象实现。即:

①将将要上传的数据存储到FormData对象中;
    ② 将processData属性的值设置为false,告诉浏览器发送对象请求数据
    ③ 将contentType属性的值设置为false,设置请求数据的类型为二进制类型。
    ④ 正常发送ajax请求即可

前端代码编写

为了方便演示,通过JSP编写网页代码,举例如下:

<%--Created by IntelliJ IDEA.User: 13241Date: 2022/3/1Time: 20:52To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>主页</title>
</head>
<body>文件上传demo<form enctype="multipart/form-data"><%--普通数据--%><p><label for="user">用户:</label><input id="user" type="text" name="username"/></p><%--二进制文件数据--%><p><label for="file">文件:</label><input id="file" type="file" name="file"/> <br><a id="uploadFile" href="javascript:void(0)" onclick="upload()">立即上传</a></p><p><input id="btnsubmit" type="submit" value="提交"/></p></form><script type="text/javascript" src="./js/jquery-3.6.0.min.js"></script><script type="text/javascript">function upload(){//获取要上传的文件var file=document.getElementById("file").files[0];//二进制文件数据var username=document.getElementById("user").value;//普通数据if (file==undefined){alert("请先选择文件.")return false;}//将文件放入formData对象中var formData=new FormData();formData.append("file",file);formData.append("username",username);//ajax发送数据$.ajax({headers: {//有需要的话-添加token'token':"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDcyNzM0MTEsImVtYWlsIjoiMTMyNDE1NjkyMEBxcS5jb20ifQ.EQYaVAMMqumGLKid_5EPhdz2VBJQBTbGFSDfdBYPwlM",},url:"/stasys_v3/upload/file",type:"POST",data:formData,processData:false,contentType:false,success:function (result) {console.log(result)}})}</script>
</body>
</html>

文件上传-后端处理

前端通过Ajax,借助FormData对象上传二进制流文件数据,在后端的业务逻辑处理,需要借助commons-fileupload、commons-io开发包实现。

 <!--文件上传依赖--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.8.0</version></dependency>

在编写代码时,需要在SpringMVC配置文件中,配置文件上传解析组件,具体配置如下:

  <!--文件上传解析组件id必须为multipartResolverspringmvc默认使用该id找该组件--><beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!--单个文件的最大大小(以字节为单位)-1024*1024*512=512M--><property name="maxUploadSizePerFile" value="536870912"/></bean>

后端处理后,可以将文件存储的链接/地址包含在json对象中响应给浏览器前端。例如:

{state:true,msg:“服务器繁忙”,url:”上传成功的资源的请求地址”}

后端代码编写

package com.xwd.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;@Controller
@RequestMapping(value = "/upload")
public class UploadController {//methods@RequestMapping(value = "/file")@ResponseBodypublic Map<String,Object> uploadFile(@RequestParam(value = "file") MultipartFile file,@RequestParam(value = "username") String username,HttpServletRequest request){System.out.println(file);System.out.println("username="+username);//获取protocol通信协议String scheme = request.getScheme();// http//获取服务名称String serverName = request.getServerName();//localhost//获取端口号int serverPort = request.getServerPort();//8010//contextPathString contextPath = request.getContextPath();// /stasys_v3String url=scheme+"://"+serverName+":"+serverPort+contextPath+"/upload/";Map<String,Object> map=new HashMap<>();// 控制文件大小if(file.getSize()>1024*1024*512){map.put("status",false);map.put("message", "文件大小不能超过512M");map.put("url",null);return map;}try {//保存文件到当前项目根目录下String realPath = request.getServletContext().getRealPath("/upload");File dir=new File(realPath);//判断目录是否存在if (!dir.exists()){dir.mkdirs();//不存在-创建新目录}//获取文件名String originalFilename = file.getOriginalFilename();//使用UUID替换文件名——避免文件名冲突String uuid= UUID.randomUUID().toString();//获取文件拓展名String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));//  控制文件类型if(!extendsName.equals(".zip")){map.put("status",false);map.put("message", "文件类型错误,必须为.zip压缩文件");map.put("url",null);return map;}//新的文件名-056af4c8-2a5a-4e6e-a108-45f689865264.zipString newFileName=uuid.concat(extendsName);//文件对应URL路径:http://localhost:8010/stasys_v3/upload056af4c8-2a5a-4e6e-a108-45f689865264.zipString fileUrl = url.concat(newFileName);//文件保存位置File saveLoc = new File(dir,newFileName);//保存文件file.transferTo(saveLoc);//填充返回值map.put("status",true);map.put("msg","文件上传成功!");map.put("url","");}catch (Exception e){e.printStackTrace();map.put("status",false);map.put("msg","文件上传失败!");map.put("url",fileUrl);}System.out.println(map.toString());return map;}
}

消息响应

文件服务器-分服务器文件上传

后端开发-服务器职责


    常见的服务器类型,例如:
    数据库服务器:运行数据库,提供基本属性数据的读写服务。
    缓存和消息服务器:负责处理高并发访问的数据缓存和消息
    文件服务器:负责存储用户上传的文件的服务器。
    应用服务器:用于部署JavaWeb应用。
    在实际开发中,会有很多职责不同的服务器,通过合理分工,可以提升项目的运行效率。

将Tomcat服务器作为文件服务器

制作并启动文件服务器

可单独解压一个Tomcat,作为文件服务器。
    【0】创建文件保存文件夹:upload

【1】配置文件服务器Server端口号:8006

<!-- Note:  A "Server" is not itself a "Container", so you may notdefine subcomponents such as "Valves" at this level.Documentation at /docs/config/server.html-->
<Server port="8006" shutdown="SHUTDOWN"><Listener className="org.apache.catalina.startup.VersionLoggerListener" />

【2】修改连接器端口号为:8090

    <!-- A "Connector" represents an endpoint by which requests are receivedand responses are returned. Documentation at :Java HTTP Connector: /docs/config/http.htmlJava AJP  Connector: /docs/config/ajp.htmlAPR (HTTP/AJP) Connector: /docs/apr.htmlDefine a non-SSL/TLS HTTP/1.1 Connector on port 8080--><Connector port="8090" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

【3】设置远程服务器非只读,修改web.xml中servlet初始化参数readOnly为false.

        <init-param><param-name>readonly</param-name><param-value>false</param-value></init-param>

【4】启动文件服务器

SSM项目:添加跨服务文件上传依赖

 <!--跨服务文件上传依赖--><dependency><groupId>com.sun.jersey</groupId><artifactId>jersey-client</artifactId><version>1.19</version></dependency>

跨服务器文件上传:前端代码编写

前端代码无需改动。

跨服务器文件上传:后端代码编写

后端代码改动如下。

package com.xwd.controller;import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;/*** @ClassName UploadController* @Description: com.xwd.controller* @Auther: xiwd* @Date: 2022/3/14 - 03 - 14 - 22:56* @version: 1.0*/
@Controller
@RequestMapping(value = "/upload")
public class UploadController {//propertiesprivate final static String FileServerDir="http://192.168.0.104:8090/upload/";//setter//getter//constructors//methods@RequestMapping(value = "/file")@ResponseBodypublic Map<String,Object> uploadFile(@RequestParam(value = "file") MultipartFile file,@RequestParam(value = "username") String username,HttpServletRequest request){System.out.println(file);System.out.println("username="+username);//获取protocol通信协议String scheme = request.getScheme();// http//获取服务名称String serverName = request.getServerName();//localhost//获取端口号int serverPort = request.getServerPort();//8010//contextPathString contextPath = request.getContextPath();// /stasys_v3String url=scheme+"://"+serverName+":"+serverPort+contextPath+"/upload/";Map<String,Object> map=new HashMap<>();// 控制文件大小if(file.getSize()>1024*1024*512){map.put("status",false);map.put("message", "文件大小不能超过512M");map.put("url",null);return map;}try {//保存文件到当前项目根目录下String realPath = request.getServletContext().getRealPath("/upload");File dir=new File(realPath);//判断目录是否存在if (!dir.exists()){dir.mkdirs();//不存在-创建新目录}//获取文件名String originalFilename = file.getOriginalFilename();//使用UUID替换文件名——避免文件名冲突String uuid= UUID.randomUUID().toString();//获取文件拓展名String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));//  控制文件类型if(!extendsName.equals(".zip")){map.put("status",false);map.put("message", "文件类型错误,必须为.zip压缩文件");map.put("url",null);return map;}//新的文件名-056af4c8-2a5a-4e6e-a108-45f689865264.zipString newFileName=uuid.concat(extendsName);//创建sun公司提供的jersey包中的com.sun.jersey.api.client.Client类的对象Client client = Client.create();//提供文件服务器存储路径-http://192.168.0.104:8090/+新文件名WebResource webResource = client.resource(FileServerDir+newFileName);//提供文件的二进制数据file.getBytes()——保存文件到另一个服务器webResource.put(String.class, file.getBytes());//填充返回值map.put("status",true);map.put("msg","文件上传成功!");map.put("url",FileServerDir+newFileName);}catch (Exception e){e.printStackTrace();map.put("status",false);map.put("msg","文件上传失败!");map.put("url",null);}System.out.println(map.toString());return map;}
}

补充:基于Axios+Element UI文件上传方案

后端代码

后端代码同改动之后的跨服务器文件上传代码一致。

Element UI组件使用与Axios数据请求

el-upload上传组件

使用Element UI的el-upload上传组件。

          <el-form-item label="实证文件:"><el-uploadclass="upload-demo":file-list="form.filelist":show-file-list="true"dragaction="http://www.baidu.com":before-upload="beforeUpload":on-change="addFile":on-success="uploadSuccess":multiple="false":auto-upload="false"accept=".zip":limit="1"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><div class="el-upload__tip" slot="tip">只能上传单个zip压缩文件,重复上传会导致文件覆盖</div></el-upload>

el-upload事件处理

Element UI的el-upload上传组件的事件处理函数,根据需要修改函数体代码即可。

 //文件上传之前文件类型检验beforeUpload(file) {console.log(file)},//添加文件-添加文件、上传成功和上传失败时都会被调用addFile(file, fileList) {//记录文件名称this.form.evidence = this.form.email + new Date().getTime() + file.name//记录文件对象this.form.file = fileconsole.log(this.form.file)console.log(this.form.evidence)},//文件上传成功uploadSuccess(response, file, fileList) {console.log(response)console.log(file)console.log(fileList)},

Axios发送文件上传请求

使用Axios发送文件上传请求。

axios({ headers: { 'Content-Type': 'multipart/form-data' }, url: 'http://localhost:8010/stasys_v3/upload/file', method: 'POST', data: formData, }) .then((res) => { console.log(res) if (res.data && res.data.status) { //文件已上传成功this.$message({ message: '文件已上传!', type: 'success', }) } else { this.$message.error('文件上传失败!') } }) .catch((error) => { console.log(error) this.$message.error('信息上报失败!') })

响应结果如下:

msg: "文件上传成功!"
​status: true
​url: "http://192.168.0.104:8090/upload/ca71cdb0-9245-4091-a623-1b1be4fa5ed3.zip"

SSM-文件上传方案相关推荐

  1. pupload 文件分块 php,基于Plupload实现Base64分割的文件上传方案

    标题:基于Plupload实现Base64分割的文件上传方案 关键词:文件上传.Base64.Plupload.Blob.分割上传 领域:Web前端 作者:孙振强 日期:2018-04-13 目录 背 ...

  2. axios文件上传 formdata_基于业务场景下的图片/文件上传方案总结

    图片/文件上传组是企业项目开发中必不可少的环节之一, 但凡涉及到用户模块的都会有图片/文件上传需求, 在很多第三方组件库(ant desigin, element ui)中它也是基础组件之一. 接下来 ...

  3. SSM文件上传封装工具类

    SSM项目中文件上传controller层中文件上传代码重复过多,将其封装成工具类,方便以后的使用. resource.properties NOTICE_IMAGE_DIR=E:/upload/no ...

  4. mysql数据文件有10g_百万行mysql数据库优化和10G大文件上传方案

    最近这几天正在忙这个优化的方案,一直没时间耍,忙碌了一段时间终于还是拿下了这个项目?项目中不要每次都把程序上的问题,让mysql数据库来承担,它只是个mysql而已. 问题1:针对MySQL Comm ...

  5. 再次分享一个多选文件上传方案“.NET研究”

    多选文件上传,已经非常多了,选择性多了可能有时候要比较下哪个更合适,结合到项目中使用更方便才是最重要的.很多的多选上传基本上都是调用的swf文件,确实用flash 或flex开发一个多选上传的功能很方 ...

  6. 再次分享一个多选文件上传方案

    多选文件上传,已经非常多了,选择性多了可能有时候要比较下哪个更合适,结合到项目中使用更方便才是最重要的.很多的多选上传基本上都是调用的swf文件,确实用flash 或flex开发一个多选上传的功能很方 ...

  7. 求超大文件上传方案( Web )

    需求: 项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制. PC端全平台支持,要求支持Window ...

  8. http超大文件上传方案

    需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...

  9. 关于ssm文件上传报错400,面对错误我们只能说亚麻跌,达咩,达咩哟!

    这个问题困扰了我很久,研究了很久之后发现是一些小细节问题!!太难了! 我是一开始把文件上传的控制器方法中的MultipartFile的形参定为filename,表单中input也设置为filename ...

  10. 求超大文件上传方案( js )

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

最新文章

  1. 编写优质代码的 6 大关键方法
  2. 中国电信的新媒体营销尝试
  3. 计算机控制刘世荣习题,谢谢你,曾经允许我不爱刘世荣①星期一的早晨,我紧张而又兴奋,因...
  4. kettle组件-查询
  5. 首次摆脱对梯度的依赖,CMU等开源Score-CAM:基于置信分数的视觉可解释性
  6. 定时执行程序-Quartz简单实例
  7. 每日一linux命令
  8. sql server 2014安装方法教程
  9. 苹果七绕过基带激活2020_苹果漏洞,可跳过苹果激活锁
  10. 漫步最优化二十二——收敛速率
  11. Delphi 7下最小化到系统托盘
  12. SSL 1108——【USACO 2.1】海明码(DFS)
  13. Asp.Net细节性问题精萃
  14. Eclipse中Build Workspace 优化
  15. C++ 编译运行报错 error: stray ‘\200’ in program 解决方案
  16. CSS/HTML/JS实现图片轮播
  17. Windows网络编程获得本机IP地址
  18. 电子地图“顽疾”难治,会“传染”自动驾驶专用高精地图吗?
  19. linux 卸载aria2,Linux一键安装Aria2 + AriaNg + Filebrowser
  20. Set与List的前辈是Collection,Map自成一派

热门文章

  1. Live800:服务经济时代,企业如何满足客户需求?
  2. mysql回调地狱_浅谈JS回调地狱
  3. Axialis IconWorkshop
  4. phpStorm 破解码
  5. java.awt.Color颜色十进制代码
  6. html js引用本地资源,了解使用JavaScript读取本地文件的方法
  7. 面试-python基础知识
  8. 扩展敏捷性:选择敏捷框架之前要问的问题
  9. python waitkey_OpenCV Python视频播放 – 如何为cv2.waitKey()设置正确的延迟
  10. Android实现批量照片上传至服务器,拍照或者从相册选择