springboot上传文件到阿里oss

       近两天公司业务需要上传图片,在自己搭建文件上传服务器、使用七牛云存储、使用阿里oss对象存储这几种方式对比后,最终选择了阿里的oss方式。

       下面是使用流程:

        首先要注册个阿里的主张号,然后进入到管理控制台,选择产品服务,找到对象存储oss选项,没开通过的,先开通,具体细节不做详细讲解,主要上代码。

1.这个是controller层的

/**
* 图片上传
* @author XXX
* @date 2018/5/19
*/

@RestController

@RequestMapping("/comm")

public class CommonController {

//上传图片

@RequestMapping(value = "/upPicFile", method = RequestMethod.POST)
public Result upPicFile(HttpServletRequest request) throws Exception{
return ResultGenerator.genSuccessResult(fileParase(1,request));

}

//上传视频

@RequestMapping(value = "/upVidFile", method = RequestMethod.POST)
public Result upVidFile(HttpServletRequest request) throws Exception{

return ResultGenerator.genSuccessResult(fileParase(2,request));

}

//公用方法(视频或图片)

private List<String> fileParase(int type,HttpServletRequest request) throws Exception{
List<String> allFileName=new ArrayList<String>();

int totalBytes = request.getContentLength();
String contentType = request.getContentType();
int position = contentType.indexOf("boundary=");

String startBoundary = "--" + contentType.substring(position+"boundary=".length());
String endBoundary = startBoundary + "--";
//将request的输入流读入到bytes中
InputStream inputStream = request.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
byte[] bytes = new byte[totalBytes];
dataInputStream.readFully(bytes);
dataInputStream.close();
//将字节读入到字符流中
BufferedReader reader = new BufferedReader(new StringReader(new String(bytes)));

int temPosition = 0;
boolean flag = false;
int end = 0;
while(true){
//当读取一次文件信息后
if(flag){
bytes = subBytes(bytes, end, totalBytes);
temPosition = 0;
reader = new BufferedReader(new StringReader(new String(bytes)));
}
//读取一行的信息:------WebKitFormBoundary5R7esAd459uwQsd5,即:lastBoundary
String str = reader.readLine();
//换行算两个字符
temPosition += str.getBytes().length + 2;
//endBoundary:结束
if(str==null||str.equals(endBoundary)){
break;
}
//表示头信息的开始(一个标签,input,select等)
if(str.startsWith(startBoundary)){
//判断当前头对应的表单域类型
str = reader.readLine(); //读取当前头信息的下一行:Content-Disposition行
temPosition += str.getBytes().length+2;
int position1 = str.indexOf("filename="); //判断是否是文件上传
if(position1 != -1){
//读取行,such as:Content-Type: image/jpeg,记录字节数,此处两次换行
//解析当前上传的文件对应的name(input标签的name),以及fieldname:文件名
// int position2 = str.indexOf("name=");
//去掉name与filename之间的"和;以及空格
// String name = str.substring(position2 + "name=".length() + 1, position1-3);
//去掉两个"
String filename = str.substring(position1 + "filename=".length() + + 1,str.length() - 1);
String suffix=filename.substring(filename.indexOf("."));
temPosition += (reader.readLine().getBytes().length + 4);
end = this.locateEnd(bytes, temPosition, totalBytes, endBoundary);
byte[] destBytes = new byte[end-temPosition-2];
System.arraycopy(bytes, temPosition, destBytes, 0, end-temPosition-2);
if(type==1) {
allFileName.add(OSSUtils.uploadPicWithStream(suffix, destBytes));
}
if(type==2) {
allFileName.add(OSSUtils.uploadVidWithStream(suffix, destBytes));
}
flag = true;
}
}
}
return allFileName;
}


/**
* 定位当前头信息的结束位置
* @param bytes
* @param start :开始位置
* @param end :结束位置
* @param endStr :比较字符串
* @return
* TODO
*/
public int locateEnd(byte[] bytes,int start,int end,String endStr){
byte[] endByte = endStr.getBytes();
for(int i=start+1;i < end ; i ++){
if ( bytes [ i ]= =endByte[0]){
int k = 1 ;
while ( k < endByte . length ){
if ( bytes [ i + k ] != endByte [ k ]){
break ;
}
k ++;
//返回结束符的开始位置
if ( k = = endByte . length ){
return i ;
}
}
}

return 0;

}


private static byte[] subBytes(byte[] b, int from, int end) {
byte[] result = new byte[end - from];
System.arraycopy(b, from, result, 0, end - from);
return result;
}

}

     2. OSSUtils工具类

public class OSSUtils {
/**
* 上传文件
* @param name 想要保存的名字
* @param filename 文件的全名
*/
public static void uploadingFile(String name,String filename){
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(OSSCommons.FILEENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
//上传
ossClient.putObject(OSSCommons.PICTUREBUCKET, name, new File(filename));
ossClient.shutdown();

}

/**
* 文件下载
* @param name 想要下载文件名字
* @param filename 文件的保存名字
* @throws IOException
*/
public static void downloadFile(String name,String filename) throws IOException {
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(OSSCommons.FILEENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
// 下载object到文件
ossClient.getObject(new GetObjectRequest(OSSCommons.PICTUREBUCKET, name), new File(filename));
// 关闭client
ossClient.shutdown();
}

/**
* 视频断点上传
* @param name 想要保存的名字
* @param filename 文件的全名
* @throws Throwable
*/
public static void uploadingVideo(String name,String filename) throws Throwable {
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(OSSCommons.VIDEOENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
// 设置断点续传请求
UploadFileRequest uploadFileRequest = new UploadFileRequest(OSSCommons.VIDEOBUCKET, name);
// 指定上传的本地文件
uploadFileRequest.setUploadFile(filename);
// 指定上传并发线程数
uploadFileRequest.setTaskNum(5);
// 指定上传的分片大小
uploadFileRequest.setPartSize(1 * 1024 * 1024);
// 开启断点续传
uploadFileRequest.setEnableCheckpoint(true);
// 断点续传上传
ossClient.uploadFile(uploadFileRequest);
// 关闭client
ossClient.shutdown();
}

/**
* 视频断点下载
* @param name 想要下载文件名字
* @param filename 文件的保存名字
* @throws Throwable
*/
public static void downloadVideo(String name,String filename) throws Throwable {
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(OSSCommons.VIDEOENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
// 下载请求,10个任务并发下载,启动断点续传
DownloadFileRequest downloadFileRequest = new DownloadFileRequest(OSSCommons.VIDEOBUCKET, name);
downloadFileRequest.setDownloadFile(filename);
downloadFileRequest.setTaskNum(10);
downloadFileRequest.setEnableCheckpoint(true);
// 下载文件
DownloadFileResult downloadRes = ossClient.downloadFile(downloadFileRequest);
// 下载成功时,会返回文件的元信息
downloadRes.getObjectMetadata();
// 关闭client
ossClient.shutdown();
}

/**
* 流方式上传图片
*
* @param
* @return
* @throws Exception
*/
public static String uploadPicWithStream(String suffix,byte[] bytes) throws Exception {
OSSClient ossClient = new OSSClient(OSSCommons.FILEENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
String fileName = System.currentTimeMillis() + suffix;
try {
ossClient.putObject(OSSCommons.PICTUREBUCKET, fileName, new ByteArrayInputStream(bytes));
ossClient.shutdown();
return OSSCommons.pictureURL_PREFIX.concat(fileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* 流方式上传图片
*
* @param
* @return
* @throws Exception
*/
public static String uploadVidWithStream(String suffix,byte[] bytes) throws Exception {
OSSClient ossClient = new OSSClient(OSSCommons.VIDEOENDPOINT, OSSCommons.ACCESSKEYID, OSSCommons.ACCESSKEYSECRET);
String fileName = System.currentTimeMillis() + suffix;
try {
ossClient.putObject(OSSCommons.VIDEOBUCKET, fileName, new ByteArrayInputStream(bytes));
ossClient.shutdown();
return OSSCommons.VIDEOURL_PREFIX.concat(fileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

}

3.OSSCommons配置类

public class OSSCommons {
//视频下载前缀
public static final String VIDEOURL_PREFIX="阿里oss管理控制台中去找";
//文件预览前缀
public static final String pictureURL_PREFIX="阿里oss管理控制台中去找";
//文件服务器接口地址
public static final String FILEENDPOINT = "阿里oss管理控制台中去找";
//视频服务器接口地址
public static final String VIDEOENDPOINT = "阿里oss管理控制台中去找";
//阿里账号
public static final String ACCESSKEYID = "阿里oss管理控制台中去找";
public static final String ACCESSKEYSECRET = "阿里oss管理控制台中去找";
//文件桶名
public static final String PICTUREBUCKET = "阿里oss管理控制台中去找";
//视频桶名
public static final String VIDEOBUCKET = "阿里oss管理控制台中去找";
}

4.pom.xml文件依赖配置

<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>

</dependency>

好了,到这里后台的就完事了

下面就是前端调用的代码了

我这里前端使用的vue框架(elementUi,自己网上去找,就是用的这个风格)

let formData = new FormData ();
formData . append ( "imgStream" , file );
          
  $ . ajax ({
     url:urlTemp ,
type: 'POST' ,
processData: false ,// 不处理数据
contentType : false ,// 不设置内容类型
data:formData ,
dataType: "json" ,
success : function ( res ){
//截取最后一个斜杠后的内容(返回的数据是能够访问的图片地址,所以我这里截取了文件名称)
let temp = res . data [ 0 ];
let index = temp . lastIndexOf ( " \/ " );
let str = temp . substring ( index + 1 , temp . length );

//后面的自己根据业务逻辑去实现...
}
}
});

上诉前端代码用到的formData  、processData、contentType 这几个概念不清楚的自己去百度扫盲

这块就到这里了,代码复制过去可以直接用的,能用的上的自己拿去用,欢迎讨论


猜你喜欢

转载自blog.csdn.net/kaola_l/article/details/80425791