前言:
  Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务).

铺垫:
  文件上传是很基础的东西, 没有高深的理论背景. 因此这边不再具体阐述和"科普", ^_^.
  对于javaer而言, 实现文件上传功能需要用到commons-fileupload和commons-io组件.
  Ok, Let's Go!

页面编写:
  文件上传的form表单非常的简单:

<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中, 添加入如下依赖项:

<!-- 上传文件的支持 -->
<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类进行文件上传的处理:

@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;
  } }

  好想非常的简单, 然而当满怀信心去尝试运行的时候, 结果却如下的错误信息.

Expected MultipartHttpServletRequest: is a MultipartResolver configured?

  正如错误体所所指示的, 需要添加一个MultipartResolver实例于SpringMVC中即可.

<!-- 对上传文件的支持 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!-- 上传文件大小为10M -->
  <property name="maxUploadSize" value="10485760" />
</bean>

  再次运行, 基本上就没问题了.

本地保存:
  对于本地存储而言, 关键还是如何获取webapp的根目录.
  方法一: 配置系统属性
  配置web.xml, 通过注册listener设置目录于系统属性中.

<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代码获取到:

String realPath = System.getProperty("app.yourweb.com");

  方法二: 借助ServletContext来获取webapp根目录

HttpServletRequest request = ...;
request.getSession().getServletContext().getRealPath("/");

  这两种方式都可以, 那种简洁就使用那种.

OSS存储:
  使用云存储服务来保存文件, 是种被推荐的做法, 现在也越来越流行. 淘宝这么多图片, 一个图片文件系统, 轻轻松松的简化开发的工作量.
  参考官方文档: OSS Java API手册
  OSS中, bucket全局唯一, 这个需要注意, OSSClient是线程安全的.
  • OSSClient的实例化和基础配置:

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);

  • 上传文件代码(摘自官网):

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代码(摘自官网):

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:

String endpoint = ...;
String bucketName = ...;
String key = ...; String url = endpoint + "/" + bucketName + "/" + key;

  下面这种, 更简单直接一点.
  OSS的操作看似非常简单, 但真正自己去实践的时候, 难免遇到一些坑.
  比如如下错误:

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/.

springmvc学习笔记--支持文件上传和阿里云OSS API简介的更多相关文章

  1. SpringMVC:学习笔记(8)——文件上传

    SpringMVC--文件上传 说明: 文件上传的途径 文件上传主要有两种方式: 1.使用Apache Commons FileUpload元件. 2.利用Servlet3.0及其更高版本的内置支持. ...

  2. Windows环境下用C#编程将文件上传至阿里云OSS笔记

    Windows环境下用C#编程将文件上传至阿里云OSS笔记 本系列文章由ex_net(张建波)编写,转载请注明出处. http://blog.csdn.net/ex_net/article/detai ...

  3. Java下载https文件上传到阿里云oss服务器

    Java下载https文件上传到阿里云oss服务器 今天做了一个从Https链接中下载音频并且上传到OSS服务器,记录一下希望大家也少走弯路. 一共两个类: 1 .实现自己的证书信任管理器类 /** ...

  4. SpringMVC学习笔记八:文件上传及多个文件上传

    SpringMVC实现文件上传需要加入jar包,commons-fileupload-1.3.1.jar,commons-io-2.2.jar 项目目录树: pom.xml加入需要的包 <pro ...

  5. django 文件上传(阿里云oss)下载(支持大文件下载)

    1.文件上传 Models 设计 class Upload_File(models.Model): image = models.FileField(upload_to='file/%Y/%m',de ...

  6. ThinkPHP 文件上传到阿里云OSS上(干货)

    参考:http://www.thinkphp.cn/extend/789.html 1.前往阿里云github下载SDK包:https://github.com/aliyun/aliyun-oss-p ...

  7. 备份MySQL数据库并上传到阿里云OSS存储

    1. 环境配置 要将本地文件上传到阿里云oss中, 必须使用阿里云提供的工具 ossutil, 有32位,也有64位的, Linux和Windows都有.具体可以到阿里云官网下载 官网及文档: htt ...

  8. Django:学习笔记(8)——文件上传

    Django:学习笔记(8)——文件上传 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不 ...

  9. JavaScript进阶(九)JS实现本地文件上传至阿里云服务器

    JS实现本地文件上传至阿里云服务器 前言 在前面的博客< JavaScript进阶(八)JS实现图片预览并导入服务器功能>(点击查看详情)中,实现了JS将本地图片文件预览并上传至阿里云服务 ...

随机推荐

  1. 初学画布canvas的chapter1

    ——这篇读后感是我阅读<写给Web开发人员看的HTML5教程>一书中的第5章画布后的小小看法,由于编程实力有限,很多效果病没有一一去实现,所以只是停留在纸上谈兵的阶段. 画布(canvas ...

  2. GZFramwork数据库层《前言》DLL项目引用

    新建项目: 1. 项目引入GZFramwork.dll NuGet地址:Install-Package GZFramwork 每个项目都引用 2.BLL层 设置数据库连接维护类:继承于:GZFramw ...

  3. 【springMVC】简单的前后端数据交流

    最最常见两种,一则返回视图模板(文档),二则为json数据.就使用一个源代码文件来看看springmvc是怎么做到的. 1.UserController.java源代码文件 (这里额外的使用了fast ...

  4. java高薪之路__002_异常处理

    自定义异常 package learn.JavaBasics.Class; import java.util.Date; /** * 如何自定义一个异常类 * 1. 继承一个现有的异常类 * 2. 提 ...

  5. 做个这样的APP要多久?[转]

    这是一个“如有雷同,纯属巧合”的故事,外加一些废话,大家请勿对号入座.开始了…… 我有些尴尬地拿着水杯,正对面坐着来访的王总,他是在别处打拼的人,这几年据说收获颇丰,见移动互联网如火如荼,自然也想着要 ...

  6. (function($){}) 和$(function(){}) 和$(function($){}) 区别

    请问下(function($){}) 和$(function(){}) 和$(function($){}) 有什么区别 谢谢 一.先看 jQuery(function(){ }); 全写为 jQuer ...

  7. 在内部架设NuGet服务器(转载)

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com 在公司内部有 ...

  8. 一些常用的方法(1)--去除DataTable中的重复数据

    private DataTable Display(DataTable dtSource)        {            DataTable dtTemp = dtSource.Copy() ...

  9. WCF初探-12:WCF客户端异常处理

    前言: 当我们打开WCF基础客户端通道(无论是通过显式打开还是通过调用操作自动打开).使用客户端或通道对象调用操作,或关闭基础客户端通道时,都会在客户端应用程序中出现异常.而我们知道WCF是基于网络的 ...

  10. sql server 子找父和父找子

    父找子 with RTD1 as( select Id,pid from Sys_XCode ), RTD2 as( select * from RTD1 where id=1 union all s ...