这也是新浪开始启用防盗链后的另一种解决方案,当然为了省钱需要复杂点的操作。

准备

  • 阿里云服务器
  • 开通对象储存OSS
  • 新建一个Bucket
  • 百度

Spring中的简单使用

参考官方文档后 maven配置:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.8.3</version>
</dependency>

为了方便可以写个工具类:

public class AliOSSUtil {
    //创建OSSClient实例
    public static OSSClient getOSSClient(String endpointYml,String accessKeyIdYml,String accessKeySecretYml) {
        OSSClient ossClient = new OSSClient(endpointYml, accessKeyIdYml, accessKeySecretYml);
        return ossClient;
    }
	
	   /**
     *
     * @Title: uploadByInputStream
     * @Description: 通过输入流上传文件
     * @param ossClient 	oss客户端
     * @param inputStream 	输入流
     * @param bucketName 	bucket名称
     * @param objectName 	上传文件目录和(包括文件名) 例如“test/1.jpg”
     * @return void 		返回类型
     * @throws
     */
    public static void uploadByInputStream(OSSClient ossClient, InputStream inputStream, String bucketName,
                                           String objectName) {
        try {
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	}

接口:

public interface DistributeFactory {

   /**
     *  单个文件上传,也可以改为集合
     * @param file
     * @return
     * @throws IOException
     */
    public  String imgDistribute(MultipartFile file) throws IOException;
}

实现:

@Component
public class AliOssDistributeFactory implements DistributeFactory {

    //文件存储目录
    private static final String FILE_DIR = "你的路径/";
    // bucket名称
    private static final String BUCKET_NAME = "你的bucketName";
    // 外网访问http头,也就是Bucket 域名
    private static final String HTTP_PATH = "Bucket 域名";
	//文件后缀
    private static final String FILE_EXTENSION = ".png";
	//对应的配置
    @Value("${aliyun.config.ossEndPoint}")
	private String endpointYml;//文件上传的ossEndPoint地域节点,对应的服务器直接使用内网。

    @Value("${aliyun.config.accessKeyId}")
    private String accessKeyIdYml;

    @Value("${aliyun.config.accessKeySecret}")
    private String accessKeySecretYml;

    @Override
    public String imgDistribute(MultipartFile file) throws IOException {
			OSSClient ossClient = AliOSSUtil.getOSSClient(endpointYml,accessKeyIdYml,accessKeySecretYml);
			String url="";
            InputStream input = file.getInputStream();
           String fileName = getNowDate("yyyyMMddhhmmssSSS")+FILE_EXTENSION;
            AliOSSUtil.uploadByInputStream(ossClient,input,BUCKET_NAME,FILE_DIR + fileName);
            url=HTTP_PATH + FILE_DIR + fileName;
			return url;
    }
	   /**
     * 获取当前日期或者时间
     * @param format
     * @return
     */
    public static String getNowDate(String format){
        String dateString = "";
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        dateString = formatter.format(new Date());
        return dateString;
    }

}

通过内网获取OSS中的文件在外网中返回

由于在OSS的收费策略中,存储、外网访问、API调用这三项都要收费,其中外网访问的费用还挺高。

但是,在OSS的收费策略中注明了:内网访问免费。也就是说,如果我们的使用阿里云的ECS通过内网去请求OSS中的资源,是不收费的。

所以,我们现在要解决的问题就是,通过内网去请求的资源,怎么在外网中返回给访客呢?

服务器和OSS Bucket必须在同一区域

这是一个前提条件,阿里云OSS的外网访问是走的*.aliyuncs.com这个域名,而内网域名*.internal.aliyuncs.com只对对应地区的阿里云服务器开放。

ningx代理

这里可以直接使用傻瓜操作,宝塔面板。
给服务器解析一个域名后在宝塔中添加站点

file

在配置文件中加入

 # 使用OSS上面的对象
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|eot|otf|svg|ttf|woff)$ {
		expires 30d;
		proxy_pass http://你的bucket.oss-cn-你的城市-internal.aliyuncs.com;
		rewrite /(.+)$ /$1 break;
}
这样在访问上传的图片文件时,可以直接将外网路径地址替换成刚解析的域名。
当然这种方式在不配合cdn的情况下会非常的慢

最后

	将代码中的外网访问http头,也就是Bucket 域名替换成解析好的内网代理域名即可。