文件的上传&预览&下载学习(一)

摘要:
它主要解释了后端逻辑和数据库表设计1。多个主流文件上传;Try{//一个订单只有一个报告pdfQueryWrapper<response.setContentType(“application/octet流”);“attachment;response.getOutputStream());Try{Filefile=newFile(filePath);

注:主要是说明后端逻辑和数据库表设计

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

文件的上传&预览&下载学习(一)第1张

文件的上传&预览&下载学习(一)第2张

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查询,获取输入流,然后下载)

免责声明:文章转载自《文件的上传&amp;amp;预览&amp;amp;下载学习(一)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#将jpg格式图片合成到bmp格式图片中mysql全文检索下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python(48):re.split 多分隔符

问题描述: 使用多个界定符分割字符串 问题 你需要将一个字符串分割为多个字段,但是分隔符(还有周围的空格)并不是固定的。 解决方案 string 对象的 split() 方法只适应于非常简单的字符串分割情形, 它并不允许有多个分隔符或者是分隔符周围不确定的空格。 当你需要更加灵活的切割字符串的时候,最好使用 re.split() 方法: >>...

Python3 读取和写入excel

一、Excel 1、Excel文件三个对象 workbook: 工作簿,一个excel文件包含多个sheet。sheet:工作表,一个workbook有多个,表名识别,如“sheet1”,“sheet2”等。cell: 单元格,存储数据对象 2、excel定义的图 excel定义的图分两级类别描述,第一级分别有九大类,如下所示 area: 面积图bar:...

pytest 基本用法

1、断言用assert,可以进行==,!=,+,-,*,/,<=,>=,is True、False,is not True、False ,in ,not in 等判断。 import pytestdef add(a,b): return a + bdef is_prime(n): if n <= 1: retur...

下载文件夹的解决方案

ASP.NET批量下载文件的方法 这篇文章主要介绍了ASP.NET批量下载文件的方法,实例汇总了常见的asp.net实现批量下载的方法,具有一定的实用价值,需要的朋友可以参考下 本文实例讲述了ASP.NET批量下载文件的方法。分享给大家供大家参考。具体方法如下: 一、实现步骤 在用户操作界面,由用户选择需要下载的文件,系统根据所选文件,在服务器上创建用于存...

15.ThinkPHP 中间件

从5.1.6+版本开始,正式引入中间件的支持。 中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理 官方手册:https://www.kancloud.cn/manual/thinkphp5_1/564279 传统式用户过滤 通过继承基类来达到权限的判断。但在tp5.1.6之后可以使用中间件的方式更好 定义中间件 可以通过命令行指令快速生...

python爬虫(二十) select方法

有时候需要css选择器 1、通过标签名查找: <style type="text/css"> p{ background-color:pink; } </style> <body> <div class="box"> <p&...