文件上传下载
介绍
文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。
文件上传时,对页面的form表单有如下要求:
method="post" 采用post方式提交数据
enctype="multipart/form-data!采用multipart格式上传文件type="file"
使用input的file控件上传
举例:
核心代码
package com.example.demo.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import com.example.demo.common.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.UUID; @Slf4j @RestController @RequestMapping("/common") public class CommonController { @Value("${takeOutFile.fileLocaltion}") private String basePath ; @PostMapping("/upload") public Result upload(MultipartFile file){ //这里的file只是一个临时的文件存储,临时存储到某一个位置,然后待接收完毕后再转存到目标位置上,然后再把这个临时文件删除 //截取文件后缀 String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')); //生成UUID String randomUUID = UUID.randomUUID().toString(); //拼接文件最后名称,结果为文件本体名字+UUID+后缀 String fileName = file.getOriginalFilename() + randomUUID + suffix; //保证存储的位置有这个文件夹 File dir = new File(basePath); if (!dir.exists()) { //目标存储位置不存在,就创建一个文件夹 dir.mkdirs(); } try { //转存文件到指定位置+文件的名称全拼 file.transferTo(new File(basePath+fileName)); } catch (IOException e) { e.printStackTrace(); } //把文件的名字上传回去,方便后续回显读取路径 return Result.success(fileName); } /** * 文件回显接口 * @param httpServletResponse 响应对象 * @param name 上传的文件名称 * @throws IOException IO异常 */ @GetMapping("/download") public void fileDownload(HttpServletResponse httpServletResponse, String name) throws IOException { //把刚刚存的文件读取到内存中,准备回显 FileInputStream fileInputStream = new FileInputStream(new File(basePath+name)); log.info("文件存储的位置为:"+basePath+name); //把读取到内存中的图片用输出流写入Servlet响应对象里 ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream(); //可选项,选择响应类型 httpServletResponse.setContentType("image/jpeg"); //用byte数组写入,注意是小写b,不是大写,大写就是包装类了 byte[] fileArray = new byte[1024]; int length=0; try { //只要没读到数组的尾部就一直读下去,这部分是IO的内容 while ((length=fileInputStream.read(fileArray))!=-1) { //写入响应流,从0开始,写入到数组末尾长度 servletOutputStream.write(fileArray, 0, length); //把流里的东西挤出来 servletOutputStream.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { //关闭流 fileInputStream.close(); servletOutputStream.close(); } return; } }
使用阿里云上传文件
添加application.yml配置
sky: alioss: endpoint: ${sky.alioss.endpoint} access-key-id: ${sky.alioss.access-key-id} access-key-secret: ${sky.alioss.access-key-secret} bucket-name: ${sky.alioss.bucket-name}
创建工具类
@Data @AllArgsConstructor @Slf4j public class AliOssUtil { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketName; /** * 文件上传 * * @param bytes * @param objectName * @return */ public String upload(byte[] bytes, String objectName) { // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { // 创建PutObject请求。 ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes)); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } //文件访问路径规则 https://BucketName.Endpoint/ObjectName StringBuilder stringBuilder = new StringBuilder("https://"); stringBuilder .append(bucketName) .append(".") .append(endpoint) .append("/") .append(objectName); log.info("文件上传到:{}", stringBuilder.toString()); return stringBuilder.toString(); } }
注入实体类
@Component @ConfigurationProperties(prefix = "sky.alioss") @Data public class AliOssProperties { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketName; }
注入工具类
/** * 配置类,用于创建AliOssUtil对象 */ @Configuration @Slf4j public class OssConfiguration { @Bean @ConditionalOnMissingBean public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){ log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties); return new AliOssUtil(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret(), aliOssProperties.getBucketName()); } }
使用工具类
/** * 通用接口 */ @RestController @RequestMapping("/admin/common") @Api(tags = "通用接口") @Slf4j public class CommonController { @Autowired private AliOssUtil aliOssUtil; /** * 文件上传 * @param file * @return */ @PostMapping("/upload") @ApiOperation("文件上传") public Result upload(MultipartFile file){ log.info("文件上传:{}",file); try { //原始文件名 String originalFilename = file.getOriginalFilename(); //截取原始文件名的后缀 dfdfdf.png String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); //构造新文件名称 String objectName = UUID.randomUUID().toString() + extension; //文件的请求路径 String filePath = aliOssUtil.upload(file.getBytes(), objectName); return Result.success(filePath); } catch (IOException e) { log.error("文件上传失败:{}", e); } return Result.error(MessageConstant.UPLOAD_FAILED); } }