目录
前言
一、前期准备
二、文件上传
上传进度条
三、文件下载
1.流式下载
2.下载到本地
3.进度条
前言
文件上传是常见需求,一般我们不会把文件直接上传到应用服务器,因为单台服务器存储空间是有限的,不好扩展。阿里云对象存储(OSS)是一种高度可扩展的云存储服务,可以用于存储大规模数据、备份和归档、静态网站托管以及多媒体存储等应用。本文将详细介绍如何使用阿里云OSS进行文件上传和下载。
一、前期准备
1.登录阿里云官网,开通对象存储OSS
对象存储OSShttps://www.aliyun.com/product/oss
2.创建桶---Bucket
3.添加ID和密钥
注:ID和密钥不要泄露给他人
4.jar包和依赖
二、文件上传
使用文件上传,您可以将本地文件上传到OSS文件。
以下代码用于将本地文件examplefile.txt上传到目标存储空间examplebucket中exampledir目录下的exampleobject.txt文件。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.File;public class Demo {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。String objectName = "exampledir/exampleobject.txt";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。String filePath= "D:\\localpath\\examplefile.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest); } catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}
上传进度条
在上传大文件到OSS时,为了让用户知道上传进度和预估剩余时间,您可以利用OSS SDK提供的进度监听功能实现一个进度条来反馈实时的上传状态。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import com.aliyun.oss.model.PutObjectRequest;
import java.io.File;// 使用进度条,需要实现ProgressListener方法
public class PutObjectProgressListenerDemo implements ProgressListener {private long bytesWritten = 0;private long totalBytes = -1;private boolean succeed = false;public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写Object完整路径,完整路径中不能包含Bucket名称。例如exampledir/exampleobject.txt。String objectName = "exampledir/exampleobject.txt";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。String pathName = "D:\\localpath\\examplefile.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 上传文件的同时指定进度条参数。此处PutObjectProgressListenerDemo为调用类的类名,请在实际使用时替换为相应的类名。ossClient.putObject(new PutObjectRequest(bucketName,objectName, new File(pathName)).<PutObjectRequest>withProgressListener(new PutObjectProgressListenerDemo()));// 下载文件的同时指定进度条参数。此处GetObjectProgressListenerDemo为调用类的类名,请在实际使用时替换为相应的类名。
// ossClient.getObject(new GetObjectRequest(bucketName,objectName).
// <GetObjectRequest>withProgressListener(new GetObjectProgressListenerDemo()));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}public boolean isSucceed() {return succeed;}// 使用进度条需要您重写回调方法,以下仅为参考示例。@Overridepublic void progressChanged(ProgressEvent progressEvent) {long bytes = progressEvent.getBytes();ProgressEventType eventType = progressEvent.getEventType();switch (eventType) {case TRANSFER_STARTED_EVENT:System.out.println("Start to upload......");break;case REQUEST_CONTENT_LENGTH_EVENT:this.totalBytes = bytes;System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");break;case REQUEST_BYTE_TRANSFER_EVENT:this.bytesWritten += bytes;if (this.totalBytes != -1) {int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);System.out.println(bytes + " bytes have been written at this time, upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");} else {System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)");}break;case TRANSFER_COMPLETED_EVENT:this.succeed = true;System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");break;case TRANSFER_FAILED_EVENT:System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");break;default:break;}}
}
三、文件下载
1.流式下载
当下载的文件太大或者一次性下载耗时太长时,您可以通过流式下载,一次处理部分内容,直到完成文件的下载
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;public class Demo {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。关于其他Region对应的Endpoint信息,请参见访问域名和数据中心。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。String objectName = "exampledir/exampleobject.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。OSSObject ossObject = ossClient.getObject(bucketName, objectName); // 读取文件内容。System.out.println("Object content:");BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));while (true) {String line = reader.readLine();if (line == null) break;System.out.println("\n" + line);}// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。reader.close();// ossObject对象使用完毕后必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。 ossObject.close();} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (Throwable ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}
2.下载到本地
package com.aliyun.oss.demo;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import java.io.File;public class Demo {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";//从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。String objectName = "testfolder/exampleobject.txt";// 填写Object下载到本地的完整路径。String pathName = "D:\\localpath\\examplefile.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。// 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}
3.进度条
进度条用于指示上传或下载文件的进度。本文以ossClient.getObject方法为例,介绍如何使用进度条。
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import com.aliyun.oss.model.GetObjectRequest;
import java.io.File;public class GetObjectProgressListener implements ProgressListener {private long bytesRead = 0;private long totalBytes = -1;private boolean succeed = false;public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。String objectName = "testfolder/exampleobject.txt";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。String pathName = "D:\\localpath\\examplefile.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 下载文件的同时指定了进度条参数。ossClient.getObject(new GetObjectRequest(bucketName, objectName).<GetObjectRequest>withProgressListener(new GetObjectProgressListener()),new File(pathName));} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}@Overridepublic void progressChanged(ProgressEvent progressEvent) {long bytes = progressEvent.getBytes();ProgressEventType eventType = progressEvent.getEventType();switch (eventType) {case TRANSFER_STARTED_EVENT:System.out.println("Start to download......");break;case RESPONSE_CONTENT_LENGTH_EVENT:this.totalBytes = bytes;System.out.println(this.totalBytes + " bytes in total will be downloaded to a local file");break;case RESPONSE_BYTE_TRANSFER_EVENT:this.bytesRead += bytes;if (this.totalBytes != -1) {int percent = (int)(this.bytesRead * 100.0 / this.totalBytes);System.out.println(bytes + " bytes have been read at this time, download progress: " +percent + "%(" + this.bytesRead + "/" + this.totalBytes + ")");} else {System.out.println(bytes + " bytes have been read at this time, download ratio: unknown" +"(" + this.bytesRead + "/...)");}break;case TRANSFER_COMPLETED_EVENT:this.succeed = true;System.out.println("Succeed to download, " + this.bytesRead + " bytes have been transferred in total");break;case TRANSFER_FAILED_EVENT:System.out.println("Failed to download, " + this.bytesRead + " bytes have been transferred");break;default:break;}}public boolean isSucceed() {return succeed;}
}