• 瑞吉外卖08-文件上传下载


    瑞吉外卖08-文件上传下载

    需求分析

    前端介绍

    服务端介绍

    代码开发

    遇到的BUG 

    代码获取


    需求分析

    文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。

    文件上传在项目中应用非常广泛,我们经常发微博、发微信朋友圈都用到了文件上传功能。

    文件上传时,对页面的form表单有如下要求

    表单属性取值说明
    methodpost必须选择post方式提交
    enctypemultipart/form-data采用multipart格式上传文件
    typefile使用input的file控件上传

    前端介绍

    1. <form method="post" action="/common/upload" enctype="multipart/form-data">
    2. <input name="myFile" type="file" />
    3. <input type="submit" value="提交" />
    4. form>

    服务端介绍

    服务端要接收客户端页面上传的文件,通常都会使用Apache的两个组件:

    而Spring框架在spring-web包中对文件上传进行了封装,大大简化了服务端代码,我们只需要在Controller的方法中声明一个MultipartFile类型的参数即可接收上传的文件

    例如这样子 

    1. /**
    2. * 文件上传
    3. * @param file
    4. * @return
    5. */
    6. @PostMapping("/upload")
    7. public R upload(MultipartFile file){
    8. System.out.println(file);
    9. return R.success(fileName);
    10. }

    代码开发

    upload.html

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>文件上传title>
    8. <link rel="stylesheet" href="../../plugins/element-ui/index.css" />
    9. <link rel="stylesheet" href="../../styles/common.css" />
    10. <link rel="stylesheet" href="../../styles/page.css" />
    11. head>
    12. <body>
    13. <div class="addBrand-container" id="food-add-app">
    14. <div class="container">
    15. <el-upload class="avatar-uploader"
    16. action="/common/upload"
    17. :show-file-list="false"
    18. :on-success="handleAvatarSuccess"
    19. :before-upload="beforeUpload"
    20. ref="upload">
    21. <img v-if="imageUrl" :src="imageUrl" class="avatar">img>
    22. <i v-else class="el-icon-plus avatar-uploader-icon">i>
    23. el-upload>
    24. div>
    25. div>
    26. <script src="../../plugins/vue/vue.js">script>
    27. <script src="../../plugins/element-ui/index.js">script>
    28. <script src="../../plugins/axios/axios.min.js">script>
    29. <script src="../../js/index.js">script>
    30. <script>
    31. new Vue({
    32. el: '#food-add-app',
    33. data() {
    34. return {
    35. imageUrl: ''
    36. }
    37. },
    38. methods: {
    39. handleAvatarSuccess (response, file, fileList) {
    40. this.imageUrl = `/common/download?name=${response.data}`
    41. },
    42. beforeUpload (file) {
    43. if(file){
    44. const suffix = file.name.split('.')[1]
    45. const size = file.size / 1024 / 1024 < 2
    46. if(['png','jpeg','jpg'].indexOf(suffix) < 0){
    47. this.$message.error('上传图片只支持 png、jpeg、jpg 格式!')
    48. this.$refs.upload.clearFiles()
    49. return false
    50. }
    51. if(!size){
    52. this.$message.error('上传文件大小不能超过 2MB!')
    53. return false
    54. }
    55. return file
    56. }
    57. }
    58. }
    59. })
    60. script>
    61. body>
    62. html>

    CommonController 

    1. /**
    2. * 文件上传下载
    3. */
    4. @Slf4j
    5. @RestController
    6. @RequestMapping("/common")
    7. public class CommonController {
    8. @Value("${reggie.path}")
    9. private String basePath;
    10. /**
    11. * 文件上传
    12. * @param file
    13. * @return
    14. */
    15. @PostMapping("/upload")
    16. public R upLoad(MultipartFile file) {
    17. // 原始文件名
    18. String originalFilename = file.getOriginalFilename();
    19. // 获取文件类型(jpg、png)
    20. String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
    21. // 使用UUID重新生成文件名,防止文件名重复
    22. String fileName = UUID.randomUUID() + suffix;
    23. // 创建目录
    24. File dir = new File(basePath);
    25. if(!dir.exists()) {
    26. dir.mkdirs();
    27. }
    28. try {
    29. file.transferTo(new File(basePath + fileName));
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. }
    33. return R.success(fileName);
    34. }
    35. /**
    36. * 文件下载
    37. * @param name
    38. * @param response
    39. */
    40. @GetMapping("/download")
    41. public void downLoad(String name, HttpServletResponse response) {
    42. try {
    43. //输入流,通过输入流读取文件内容
    44. FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
    45. //输出流,通过输出流将文件写回浏览器
    46. ServletOutputStream outputStream = response.getOutputStream();
    47. response.setContentType("image/jpeg");
    48. int len = 0;
    49. byte[] bytes = new byte[1024];
    50. while ((len = fileInputStream.read(bytes)) != -1) {
    51. outputStream.write(bytes, 0, len);
    52. outputStream.flush();
    53. }
    54. //关闭资源
    55. outputStream.close();
    56. fileInputStream.close();
    57. } catch (Exception e) {
    58. e.printStackTrace();
    59. }
    60. }
    61. }

    遇到的BUG 

     The valid characters are defined in RFC 7230 and RFC 3986 

    【Tomcat】Error parsing HTTP request header的解决方案_SunAlwaysOnline的博客-CSDN博客icon-default.png?t=M85Bhttps://blog.csdn.net/qq_33591903/article/details/104915079

     

    1、考虑get请求头过大,而tomcat的header缓存区又过小

    那只能调整tomcat的header缓存区,在server.xml中的Connector标签中添加maxHttpHeaderSize="81920",你要是觉得不够大,可以暂时性的改成一个特别大的数值。

    如果用的是SpringBoot,则可以在application.properties文件中配置【server.tomcat.max-http-header-size=81920

    观测一段时间后,如果还是出现这个报错,那么尝试下一个解决方案。

    2、使用https去请求http协议

    建议每次打印出请求的地址和信息,使用拦截器在preHandle中打印出request的信息,看看有没有出现这样的情况。

    3、终极绝招

    有时候吧,看报错时间,都是在凌晨,这个就很奇怪。

    如果自己用的是8080端口,不妨改一个端口吧。改端口这个好像没什么科学依据,但确实能解决一部分人的问题。

    application.yml 

    1. server:
    2. port: 8080
    3. # 考虑get请求头过大,而tomcat的header缓存区又过小
    4. tomcat:
    5. max-http-form-post-size: 81920
    6. spring:
    7. application:
    8. name: reggie_take_out
    9. datasource:
    10. druid:
    11. driver-class-name: com.mysql.cj.jdbc.Driver
    12. url: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
    13. username: root
    14. password: 888888
    15. mybatis-plus:
    16. configuration:
    17. # 在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射 !!!
    18. map-underscore-to-camel-case: true
    19. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    20. global-config:
    21. db-config:
    22. id-type: ASSIGN_ID
    23. # 指定上传下载文件的缓存路径
    24. reggie:
    25. path: D:\images\

    代码获取

    瑞吉外卖: 瑞吉外卖项目完整代码,使用Sprinboot,SSM,MP,MySQL,Redis,Nginx等技术。 - Gitee.comicon-default.png?t=M85Bhttps://gitee.com/Harmony_TL/reggie_take_out/tree/reggie_v8_upload/

  • 相关阅读:
    Kubernetes应用编排与管理 —— Deployment升级策略
    [极客大挑战 2019]Knife 1(两种解法)
    亚马逊流量攻略:如何将流量转化为销售,测评实现销售飙升!
    项目开发与设计流程
    mysql备份与恢复
    关于:获取当前客户端登录的域控
    吃鸡达人必备:分享顶级干货+作图工具推荐+账号安全查询!
    11 | Spark计算数据文件中每行数值的平均值
    Selenium自动化脚本打包exe文件
    网络空间安全web向基础知识
  • 原文地址:https://blog.csdn.net/weixin_43715214/article/details/127681111