文件的上传&预览&下载学习(一)
注:主要是说明后端逻辑和数据库表设计
1.当前主流的几种文件上传&预览&下载方式
- 把文件直接存储在服务器
- 分布式存储OSS,比如阿里OSS、Minio
2.数据库表设计
- 由于文件都是跟业务关联的,比如评论里面掺杂评论图片,常规的设计就是在'评论表'添加上传'图片名称'字段和'图片相对路径',在上传成功后返回给前端
1.1 如果是加入多个文件的话,这种设计就不太合适:10个文件在评论表就需要加20个字段
1.2 针对'1.1'进行改进,建一种'文件信息表',设计字段'外键 fk_id'用来存储评论id(如果后续有商品图片也可以用这个存),这时候有需要考虑一个问题,id是根据什么生成的,是否唯一,如果是雪花ID就无需考虑这个问题,但如果是递增那极可能重复(商品id和评论id同时为1的情况);这时就还需要在'文件信息表'添加一个'外键类型 fk_type'作区分,比如评论就是comment,商品就是goods。然后把'图片名称'字段和'图片相对路径'放到'文件信息表'来(预览路径和下载路径可能不同,下载路径是绝对路径,预览路径为了防止用户直接访问服务器其他位置,做一层虚拟映射nginx)


1.3 可能还需要加一个'文件下载名称',由于文件可能是'数字+字母(可能是md5)'的形式(如果是手机拍摄),然后要按照一定的规则比如'订单编号-产品名称-用户昵称'生成
3.后端实现
1.直接使用Java下载到指定目录(现根据外键查询出绝对路径,在下载)
@Override
public void downloadByOrderId(HttpServletResponse response, Long orderId, String fkType) throws IOException {
String fileLocation = null;
try{
// 一个订单只有一个报告pdf
QueryWrapper<FileUpload> fileUploadQueryWrapper = new QueryWrapper<>();
fileUploadQueryWrapper.eq("is_deleted","0");
fileUploadQueryWrapper.eq("fk_id",orderId);
fileUploadQueryWrapper.eq("fk_type",fkType);
FileUpload uploadEntity = uploadMapper.selectOne(fileUploadQueryWrapper);
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream"); //这边可以设置文件下载时的名字,我这边用的是文件原本的名字,可以根据实际场景设置
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(uploadEntity.getOldName(), "UTF-8"));
if(StrUtil.isNotBlank(uploadEntity.getLocation())){
fileLocation = uploadEntity.getLocation();
}
logger.info("fileLocation: "+fileLocation);
FileUtils.writeBytes(uploadEntity.getLocation(), response.getOutputStream());
}catch (Exception e){
logger.error("download error orderId: {} fkType: {} && fileLocation: {} msg: {}",orderId,fkType,fileLocation,e.getMessage());
}
}
public static void writeBytes(String filePath, OutputStream os) {
FileInputStream fi = null;
try {
File file = new File(filePath);
if (!file.exists()) {
throw new FileNotFoundException(filePath);
}
fi = new FileInputStream(file);
//TODO 扩大缓冲,多线程(请求的节点过多超时)
byte[] b = new byte[8192];
int length;
while ((length = fi.read(b,0,8192)) > 0) {
os.write(b, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(os != null) {
try {
os.close();
}catch (IOException e) {
e.printStackTrace();
}
}
if(fi != null) {
try {
fi.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.分布式存储Minio,参考博客:https://www.freesion.com/article/5069848586/ (下载和上面的方式相同 根据文件名先去Minio查询,获取输入流,然后下载)
文件的上传&预览&下载学习(一)的更多相关文章
- PHP WAMP 文件上传 及 简单的上传预览
...... 使用特殊的表单类型file, 主(上传)页面: <form action="chuli.php" method="post" enctype ...
- 上传文件的三种方式xhr,ajax和iframe及上传预览
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 基于bootstrap的上传插件fileinput实现ajax异步上传功能(支持多文件上传预览拖拽)
首先需要导入一些js和css文件 ? 1 2 3 4 5 6 <link href="__PUBLIC__/CSS/bootstrap.css" rel="exte ...
- html,图片上传预览,input file获取文件等相关操作
input file常用方法: var obj=document.getElementById("upimage"); var file=obj.files[0];//获取文件数据 ...
- 用html5文件api实现移动端图片上传&预览效果
想要用h5在移动端实现图片上传&预览效果,首先要了解html5的文件api相关知识(所有api只列举本功能所需): 1.Blob对象 Blob表示原始二进制数据,Html5的file对象就继 ...
- FileReader()读取文件、图片上传预览
前言 FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据. 其中File对象可以是来自用户 ...
- 用file标签实现多图文件上传预览
效果图: js 代码: <script> //下面用于多图片上传预览功能 function setImagePreviews(avalue) { var docObj = document ...
- 模拟QQ心情图片上传预览
出于安全性能的考虑,目前js端不支持获取本地图片进行预览,正好在做一款类似于QQ心情的发布框,找了不少jquery插件,没几个能满足需求,因此自己使用SWFuplad来实现这个图片上传预览. 先粘上以 ...
- 微信开发中使用微信JSSDK和使用URL.createObjectURL上传预览图片的不同处理对比
在做微信公众号或者企业微信开发业务应用的时候,我们常常会涉及到图片预览.上传等的处理,往往业务需求不止一张图片,因此相对来说,需要考虑的全面一些,用户还需要对图片进行预览和相应的处理,在开始的时候我使 ...
- 兼容好的JS图片上传预览代码
转 : http://www.codefans.net/articles/1395.shtml 兼容好的JS图片上传预览代码 (谷歌,IE11) <html xmlns="http:/ ...
随机推荐
- 手写JS深拷贝
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue中页面渲染完成之后获取元素的属性
data() { return { message : [], }; }, watch:{ message:function(){ this.$nextTick(function(){ //方法 }) ...
- jquery.easyui.min.js:12401 Uncaught TypeError: Cannot read property 'combo' of undefined jquery.easyui.min.js:12401
踩坑中成长! jquery1.4.1升级到1.4.3 点击添加报错. 一步步调试js,发现是combox使用问题. 前端报错,未声明,js是easyui的所以只有jsp和js用法问题.看了官方用法,瞬 ...
- 关于SVN状态图标不显示的解决办法
一.参考网址 地址:https://blog.csdn.net/qq_33521184/article/details/126562881 二.详情: 第一步: 通过svn的设置来解决 右键-> ...
- vue实现自定义字体库
先看效果是不是你所需要的,再看具体如何实现. 效果如下图所示: 有些字体需要下载,用图片就会变得很不清楚,这样我们就需要去下载字体库,操作步骤如下: 首先找到需要下载的字体库 然后放在项目里面 然后定 ...
- JSON详述
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写 使用json函数需要导入json库,import json json.dumps 将p ...
- Python+Django(4)——创建其他网页(模板继承)
模板继承: 1,修改主页 父模板:抽取通用元素,在index.html同级目录下新建base.html <p> <a href="{% url 'learning_logs ...
- eset node32卸载记录
安装的是这个东西,卸载麻烦 1.一般的卸载软件比如wise program uninstall无论是普通卸载还是强制卸载都是实现不了的,火绒自带的文件粉碎是可以使用的,有两个目录要进行粉碎C:\Pro ...
- 微信小程序——石头剪刀布
博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020 作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/ ...
- 许可协议 :GPL、BSD、MIT、Mozilla、Apache和LGPL
原文摘自:https://blog.csdn.net/testcs_dn/article/details/38496107 首先借用有心人士的一张相当直观清晰的图来划分各种协议:开源许可证GPL.BS ...