springmvc学习笔记--支持文件上传和阿里云OSS API简介
前言:
Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务).
铺垫:
文件上传是很基础的东西, 没有高深的理论背景. 因此这边不再具体阐述和"科普", ^_^.
对于javaer而言, 实现文件上传功能需要用到commons-fileupload和commons-io组件.
Ok, Let's Go!
页面编写:
文件上传的form表单非常的简单:
1 2 3 4 | < form action="/test/upload_file" method="post" enctype="multipart/form-data"> 文件名: < input type="file" name="upfile"/> < br /> < input type="submit" value="提交" /> </ form > |
唯一需要注意的是, 表单enctype为multipart/form-data, 而不是默认的application/x-www-form-urlencoded.
springmvc配置:
需要引入依赖的commons-fileupload和commons-io组件.
则在maven工程的pom.xml中, 添加入如下依赖项:
1 2 3 4 5 6 7 8 9 10 11 12 | <!-- 上传文件的支持 --> < dependency > < groupId >commons-fileupload</ groupId > < artifactId >commons-fileupload</ artifactId > < version >1.3.1</ version > </ dependency > < dependency > < groupId >commons-io</ groupId > < artifactId >commons-io</ artifactId > < version >2.4</ version > </ dependency > |
编写相应的Controller类进行文件上传的处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Controller @RequestMapping (value = "/test" ) public class TestFileUploadController { @RequestMapping (value= "/upload_file" , method=RequestMethod.POST) public ModelAndView uploadFile( @RequestParam ( "upfile" ) MultipartFile upfile) { ModelAndView mav = new ModelAndView(); // TODO // save upfile return mav; } } |
好想非常的简单, 然而当满怀信心去尝试运行的时候, 结果却如下的错误信息.
1 | Expected MultipartHttpServletRequest: is a MultipartResolver configured? |
正如错误体所所指示的, 需要添加一个MultipartResolver实例于SpringMVC中即可.
1 2 3 4 5 | <!-- 对上传文件的支持 --> <bean id= "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" > <!-- 上传文件大小为10M --> <property name= "maxUploadSize" value= "10485760" /> </bean> |
再次运行, 基本上就没问题了.
本地保存:
对于本地存储而言, 关键还是如何获取webapp的根目录.
方法一: 配置系统属性
配置web.xml, 通过注册listener设置目录于系统属性中.
1 2 3 4 5 6 7 8 9 | <context-param> <param-name>webAppRootKey</param-name> <param-value>app.yourweb.com</param-value> </context-param> <!-- 添加对webapp根路径的快速访问支持 --> <listener> <listener- class >org.springframework.web.util.WebAppRootListener</listener- class > </listener> |
然后通过如下Java代码获取到:
1 | String realPath = System.getProperty( "app.yourweb.com" ); |
方法二: 借助ServletContext来获取webapp根目录
1 2 | HttpServletRequest request = ...; request.getSession().getServletContext().getRealPath( "/" ); |
这两种方式都可以, 那种简洁就使用那种.
OSS存储:
使用云存储服务来保存文件, 是种被推荐的做法, 现在也越来越流行. 淘宝这么多图片, 一个图片文件系统, 轻轻松松的简化开发的工作量.
参考官方文档: OSS Java API手册.
OSS中, bucket全局唯一, 这个需要注意, OSSClient是线程安全的.
• OSSClient的实例化和基础配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 | String accessKeyId = "your accessKeyId" ; String accessKeySecret = "your accessKeySecret" ; String bucketName = "your bucketName" ; String endpoint = "your endpoint" ; ClientConfiguration conf = new ClientConfiguration(); conf.setMaxConnections( 10 ); // 设置HTTP最大连接数为10 conf.setConnectionTimeout( 2000 ); // 设置TCP连接超时为5000毫秒 conf.setMaxErrorRetry( 3 ); // 设置最大的重试次数为3 conf.setSocketTimeout( 5000 ); // 设置Socket传输数据超时的时间为2000毫秒 // *) 进行OSS客户端的实例化 OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret, conf); |
• 上传文件代码(摘自官网):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public void putObject(String bucketName, String key, String filePath) throws FileNotFoundException { // 初始化OSSClient OSSClient client = ...; // 获取指定文件的输入流 File file = new File(filePath); InputStream content = new FileInputStream(file); // 创建上传Object的Metadata ObjectMetadata meta = new ObjectMetadata(); // 必须设置ContentLength meta.setContentLength(file.length()); // 上传Object. PutObjectResult result = client.putObject(bucketName, key, content, meta); // 打印ETag System.out.println(result.getETag()); } |
• 生成Url代码(摘自官网):
1 2 3 4 5 6 7 8 | String bucketName = "your-bucket-name" ; String key = "your-object-key" ; // 设置URL过期时间为1小时 Date expiration = new Date( new Date().getTime() + 3600 * 1000 ); // 生成URL URL url = client.generatePresignedUrl(bucketName, key, expiration); |
这个是带时效的url.
当然也可以自己拼接生成如下url:
1 2 3 4 5 | String endpoint = ...; String bucketName = ...; String key = ...; String url = endpoint + "/" + bucketName + "/" + key; |
下面这种, 更简单直接一点.
OSS的操作看似非常简单, 但真正自己去实践的时候, 难免遇到一些坑.
比如如下错误:
1 2 | The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint. |
这个问题的本质是, 阿里云的云存储是有机房概念的, 每个bucket在构建时会属于某一个机房.
endpoint默认为杭州, 若你的bucket属于其他区域, 而endpoint又没有设置一致, 就会报如上错误.
比如笔者的bucket属于上海, 则默认把endpoint设为http://oss-cn-shanghai.aliyuncs.com, 既OK.
具体可参见: OSS使用SDK访问bucket提示endpoint错误.
• 图片上传
对于图片上传, 除了在ObjectMetaData中设置文件大小以外, 还需要配置ContentType, 这个尤显得重要.
对于MIME类型, 这边也贴个链接: MIME类型大全.
总结:
文件本地存储, 并非什么难事, 主要还是体验一下OSS. 本文对springmvc文件上传做了简单的介绍, 权当学习笔记.
公众号&游戏站点:
个人微信公众号: 木目的H5游戏世界
个人游戏作品集站点(尚在建设中...): www.mmxfgame.com, 也可直接ip访问: http://120.26.221.54/.
posted on 2016-03-16 09:19 mumuxinfei 阅读(4726) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构