近期,由于项目需求需要上传图片logo,笔者在探索的过程中遇到过很多坑,今晚就把个人经验分享出来尽量少让博友们脑壳疼
①选择一个专门存储图片的服务器,这里笔者选择了第三方七牛云存储,真心感觉不错!
②前端与后台采用Ajax交互
①代码分析
File upload
②重点分析
append()
的第二个参数应是文件对象,即$('#file')[0].files[0]
。contentType
也要设置为‘false’。$('#file')[0].files[0]
中可以看到一个
标签能够上传多个文件,只需要在
里添加multiple
或multiple="multiple"
属性。对了这里的dataType一定别忘了写json,不然会解析失败的。
①导入相关依赖
com.google.code.gson
gson
2.8.0
com.squareup.okhttp3
okhttp
3.6.0
com.squareup.okio
okio
1.11.0
com.qiniu
qiniu-java-sdk
7.1.3
commons-io
commons-io
2.3
commons-fileupload
commons-fileupload
1.2.2
②定义七牛上传图片并返回外链的方法
/**
* Created by zhangxing on 2017/6/7.
*/
public class QiniuUpload {
private String picFile;
private String picUrl = "";
public QiniuUpload(String path){
picFile = path;
}
private static final String SPOT= "http://om8czer7p.bkt.clouddn.com/";//baseUrl
//设置好账号的ACCESS_KEY和SECRET_KEY
String ACCESS_KEY = "你的ACCESS_KEY"; //这两个登录七牛 账号里面可以找到
String SECRET_KEY = "你的SECRET_KEY";
//要上传的空间
String bucketname = "zhangxing"; //填写新建的那个存储空间对象的名称
//上传到七牛后保存的文件名
String key = new Date().getTime()+".jpg";
//上传文件的路径
//String FilePath = "E:\\1.jpg"; //本地要上传文件路径
//密钥配置
Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
//创建上传对象
UploadManager uploadManager = new UploadManager();
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public String getUpToken(){
return auth.uploadToken(bucketname);
}
//普通上传
public String upload() throws IOException {
try {
//调用put方法上传
Response res = uploadManager.put(picFile, key, getUpToken());
//打印返回的信息
System.out.println(res.isOK());
if(res.isOK()){
picUrl = SPOT+ key;
System.out.println(picUrl);
}else{
System.out.println("上传失败!");
}
System.out.println(res.bodyString());
} catch (QiniuException e) {
Response r = e.response;
System.out.println(r.url());
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
return picUrl;
}
}
记住,这个方法返回的是图片访问的外链。
③配置spring-web
将上述代码原原本本贴在spring-web中
④上传的controller
@RestController
@RequestMapping("qiniu")
public class QinNiuController extends BaseController {
@RequestMapping(value = "/upload",method = RequestMethod.POST)
public String upload(HttpServletResponse response,@RequestParam("file") MultipartFile file) throws IOException {
response.setHeader("Access-Control-Allow-Origin","*");
String fileName=file.getOriginalFilename();
File targetFile=new File("F:\\picture",fileName);
if(!targetFile.exists()){
targetFile.mkdirs();
}
try{
file.transferTo(targetFile);
}catch(Exception e){
e.printStackTrace();
}
String str = new QiniuUpload(targetFile.getAbsolutePath()).upload();
//str得到的是一个七牛返回的外链,然后将str存到自己的服务器
return success(str);
}
}
注意:部署到云服务器后,就不存在本地路径F盘了,
ssm项目路径代码:
String filePath = "upload/img";
String fileName=file.getOriginalFilename();
File targetFile=new File(filePath,fileName);
if(!targetFile.exists()){
targetFile.mkdirs();
}
springboot项目中路径代码:
String key="";
String fileName=file.getOriginalFilename();
// file.getInputStream();
File targetFile=new File(File.separator,fileName);
/*if(!targetFile.exists()){
targetFile.mkdirs();
}*/
//
if(fileName.endsWith(".jpg")){
key = new Date() +".jpg";
}else if(fileName.endsWith(".png")){
key = new Date()+".png";
}else if(fileName.endsWith(".gif")){
key = new Date()+".gif";
}
这样图片就临时保存在linux下的tomcat的ROOT目录下;
key表示图片的自定义名称;
⑤BaseController
public class BaseController {
protected Logger log = LoggerFactory.getLogger(getClass());
protected Logger bizErrorLog = LoggerFactory.getLogger("biz_log");
private final static ThreadLocal request = new ThreadLocal();
private final static ThreadLocal response = new ThreadLocal();
protected final Integer DEFAULT_PAGE_SIZE = 20;
public HttpServletRequest req;
public HttpServletResponse resp;
public HttpSession session;
@ModelAttribute
public void req(HttpServletResponse response,HttpServletRequest request){
this.req = request;
this.resp = response;
this.session = request.getSession();
}
@SuppressWarnings("static-access")
@ModelAttribute
public void init(final HttpServletRequest request,
final HttpServletResponse response) {
this.response.set(response);
this.request.set(request);
}
protected HttpServletRequest getRequest() {
return request.get();
}
protected HttpServletResponse getResponse() {
return response.get();
}
@InitBinder
protected void initBinder(final HttpServletRequest request,
final ServletRequestDataBinder binder) throws Exception {
binder.addValidators(new ParamValidator());
}
/**
* 获取当前用户
*/
public User getCurrentUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
Object principal = auth.getPrincipal();
if (principal instanceof User) {
User user = (User) principal;
if (user != null && !user.isAnonymous() ) {
return user;
}
}
if (auth.getClass().getSimpleName().indexOf("Anonymous") < 0) {
log.error("Unknown authentication encountered, ignore it. " + auth);
}
}
throw new BizException(GlobalErrorCode.UNAUTHORIZED, "need login first.");
}
/**
* 成功
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public String success(Object obj) {
ResponseObject result = new ResponseObject();
result.setData(obj);
String str = JSON.toJSONString(result);
String callback = getRequest().getParameter("callback");
if(!SysStringUtils.isEmpty(callback)) {
str = callback+"("+str+")";
return str;
}
return str;
}
public String chinaToUnicode(String str){
String result="";
for (int i = 0; i < str.length(); i++){
int chr1 = str.charAt(i);
if(chr1>=19968&&chr1<=171941){//汉字范围 \u4e00-\u9fa5 (中文)
result+="\\u" + Integer.toHexString(chr1);
}else{
result+=str.charAt(i);
}
}
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public String success(Object obj,String score) {
ResponseObject result = new ResponseObject();
result.setScore(score);
result.setData(obj);
return JSON.toJSONString(result);
}
public String convertToJsonp(String str) {
String callback = getRequest().getParameter("callback");
if(!SysStringUtils.isEmpty(callback)) {
str = callback+"("+str+")";
return str;
}
return str;
}
@SuppressWarnings({ "rawtypes" })
public String success() {
ResponseObject result = new ResponseObject();
return JSON.toJSONString(result,SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNonStringKeyAsString);
}
@SuppressWarnings({ "rawtypes" })
public String fail() {
ResponseObject result = new ResponseObject();
return JSON.toJSONString(result);
}
/**
* 参数不正确
*/
@SuppressWarnings({ "rawtypes" })
public String argumentError(String msg) {
ResponseObject result = new ResponseObject(GlobalErrorCode.INVALID_ARGUMENT);
result.setMoreInfo(msg);
return JSON.toJSONString(result);
}
/**
* 逻辑错误
*/
public String error(String msg) {
throw new BizException(GlobalErrorCode.UNKNOWN, msg);
}
}
好了,走完整个流程看上传效果:
好了,七牛的图片外链就拿到了,然后记得存一把数据库。
①上传类文件
public class QiniuUpload {
private String SPOT= Constant.QINIU_BASE_URL; //七牛baseUrl
private String ACCESS_KEY = Constant.QINIU_AK; //设置账号的ACCESS_KEY
private String SECRET_KEY = Constant.QINIU_SK; //设置账号的SECRET_KEY
private String bucketname = Constant.QINIU_DOMAIN;//要上传的存储空间对象的名称
private byte[] data;
private String picUrl = "";
private String key = "";
public QiniuUpload(byte[] mData, String ikey){
data = mData;
key = ikey;
}
//密钥配置
Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
//创建上传对象
UploadManager uploadManager = new UploadManager();
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public String getUpToken(){
return auth.uploadToken(bucketname);
}
//普通上传
public String upload() throws IOException {
try {
//调用put方法上传
Response res = uploadManager.put(data, key, getUpToken());
//打印返回的信息
System.out.println(res.isOK());
if(res.isOK()){
picUrl = SPOT+ key;
System.out.println("图片链接:"+picUrl);
}else{
System.out.println("上传失败!");
}
System.out.println(res.bodyString());
} catch (QiniuException e) {
Response r = e.response;
System.out.println(r.url());
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
return picUrl;
}
}
②七牛静态配置信息
//七牛相关配置信息
public static final String QINIU_DOMAIN="zhangxing";
public static final String QINIU_BASE_URL = "http://oihgq7pcj.bkt.clouddn.com/";
public static final String QINIU_AK = "Qg59MUtOKqiz-uvynQIakrJg4o7t9-LVy-0WmRto";
public static final String QINIU_SK = "XytEWfSlh3Wb7BgFQDSo7OYVNT7QOApiMQlRdzG3";
③controller代码
@CrossOrigin
@CommonsLog
@RestController
@RequestMapping("/qiniu")
public class QiNiuController extends BaseController{
private static final Logger logger = LoggerFactory.getLogger("qiniu_log");
@Autowired
private CompanyService companyService;
@PostMapping(value = "/upload/{companyId}")
public ResultInfo upload(@RequestParam("file") MultipartFile file,@PathVariable("companyId") Integer companyId) throws IOException {
String key;
if(file != null){
key = judgeFileName(file.getOriginalFilename());
}else{
return success("文件未选中");
}
String str = new QiniuUpload(file.getBytes(),key).upload();
//str得到的是一个七牛返回的外链,然后将str存到自己的服务器
int i = 0;
if(companyId != null && companyId >0){
Company company = companyService.selectByPrimaryKey(companyId) ;
company.setThumbnails(str);
i= companyService.updateByPrimaryKeySelective(company);
log.info("图片外链地址为"+str);
}
return i>0?success(str):success("上传失败");
}
/**
* 根据后缀格式定义图片名称
* @param fileName
* @return
*/
public String judgeFileName(String fileName){
if(fileName.endsWith(".jpg")){
return new Date().getTime()+".jpg";
}else if(fileName.endsWith(".png")){
return new Date().getTime()+".png";
}else if(fileName.endsWith(".gif")){
return new Date().getTime()+".gif";
}else{
return "请上传图片格式的文件";
}
}
}
效果图:
另外一种方案:将临时文件暂储在linux中/tmp下
// 获取文件名
String fileName = file.getOriginalFilename();
// 获取文件后缀
String prefix = fileName.substring(fileName.lastIndexOf("."));
// 用uuid作为文件名,防止生成的临时文件重复
File localFile = File.createTempFile(UUID.randomUUID().toString(), prefix);
// MultipartFile to File
file.transferTo(localFile);
然后引用loclFile进行真正的file上传
上传完后删除loclFile
private void deleteFile(File... files) {
for (File file : files) {
if (file.exists()) {
file.delete();
}
}
}
这样就不用为图片的临时存储路径发愁了,笔者建议使用补充形式的图片上传;好了,我是张星,欢迎加入博主技术交流群,群号:313145288