如何配置通过自定义域名访问OSS文件时实现强制下载?

通过浏览器使用自定义域名访问OSS上存储的文件时,如果您的浏览器支持预览所选的文件格式,则OSS将直接预览文件内容。如果您希望通过浏览器使用自定义域名访问OSS文件时,以附件形式下载文件,您可以通过预签名URLresponse-content-disposition字段设置为attachment来指定单次访问为强制下载,还可以通过将文件元数据Content-Disposition设置为attachment来指定所有访问为强制下载。

通过预签名URL设置单次访问为强制下载

使用OSS控制台

  1. 登录OSS管理控制台

  2. 在左侧导航栏,选择自助工具 > 签名工具

  3. 签名工具页面,单击URL签名页签。

  4. URL签名面板,按以下说明填写各项参数,其他参数保留默认配置。

    参数

    示例值

    说明

    AccessKeyId

    LTAI*********************

    填写当前账号的访问密钥AccessKey,包括AccessKey IDAccessKey Secret。使用阿里云账号或RAM用户访问时,AccessKey的获取方式,请参见创建AccessKey

    AccessKeySecret

    KZo1******************

    链接

    https://example.com/test.txt

    填写自定义域名和Object的完整路径。

    Bucket 名称

    examplebucket

    输入Object所在的Bucket名称。

    Query Params

    attachment

    下拉选择response-content-disposition,取值为attachment,效果是以原文件名的形式下载到浏览器指定路径。

  5. 单击生成链接,然后复制右侧的签名链接。

  6. 通过浏览器打开签名链接,即可实现下载。

使用阿里云SDK

Java SDK为例:

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import java.net.URL;
import java.util.*;
import java.util.Date;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // yourEndpoint填写自定义域名。
        String endpoint = "https://example.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 创建ClientBuilderConfiguration实例,您可以根据实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();

        // 将CNAME取值设置为true,用于将自定义域名绑定到目标Bucket。
        conf.setSupportCname(true);
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,例如exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "exampleobject.txt";        

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider, conf);

        try {
            // 创建请求。
            GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectName);
            // 设置HttpMethod为GET。
            generatePresignedUrlRequest.setMethod(HttpMethod.GET);
            // 设置签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
            generatePresignedUrlRequest.setExpiration(expiration);
            // 下载后显示为原Object名称。
            Map<String, String> queryParam = new HashMap<String, String>();
            queryParam.put("response-content-disposition",  "attachment");
            generatePresignedUrlRequest.setQueryParameter(queryParam);
            // 生成签名URL。
            URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
            System.out.println(url);
        } 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控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择文件管理 > 文件列表

  4. 在目标Object右侧选择更多 > 设置文件元数据

  5. 设置文件元数据面板,将Content-Disposition设置为attachment,其他参数保留默认配置,然后单击确定

  6. 在浏览器中通过自定义域名以文件URL的形式访问目标文件。

    • 以自定义域名为example.com,Bucket根目录下的文件名称为example.jpg为例(文件读写权限为公共读或者公共读写),您可以在浏览器中通过自定义域名拼接文件URL的形式(http://example.com/example.jpg)访问目标文件。

    • 以自定义域名为example.com,Bucket根目录下的文件名称为example.jpg为例(文件读写权限为私有),私有文件URL需要添加签名信息(格式为http://example.com/example.jpg?签名参数)。关于在浏览器中通过自定义域名访问私有文件的具体操作,请参见使用自定义域名访问临时文件URL

使用阿里云SDK

Java SDK为例:

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.ObjectMetadata;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

public class Test {
    public static void main(String[] args) throws Exception {

        // yourEndpoint填写自定义域名。
        String endpoint = "https://example.com";
        // 强烈建议不要把访问凭证保存到工程代码里,否则可能导致访问凭证泄露,威胁您账号下所有资源的安全。本代码示例以从环境变量中获取访问凭证为例。运行本代码示例之前,请先配置环境变量。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 创建ClientBuilderConfiguration实例,您可以根据实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();

        // 将CNAME取值设置为true,用于将自定义域名绑定到目标Bucket。
        conf.setSupportCname(true);
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
        String objectName = "testfolder/exampleobject.txt";
        // 文件内容。
        String content = "Hello OSS";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider, conf);

        try {
            // 创建上传文件的元数据,可以通过文件元数据设置HTTP标准属性。
            ObjectMetadata meta = new ObjectMetadata();

            String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes()));
            // 开启文件内容MD5校验。开启后OSS会把您提供的MD5与文件的MD5比较,不一致则抛出异常。
            meta.setContentMD5(md5);
            // 指定上传的内容类型。内容类型决定浏览器将以什么形式、什么编码读取文件。如果没有指定则根据文件的扩展名生成,如果没有扩展名则为默认值application/octet-stream。
            meta.setContentType("text/plain");
            // 下载后显示为原Object名称。如果包含有中文字符,需要进行URL编码。
            meta.setContentDisposition("attachment"+ URLEncoder.encode("UTF-8")+";"+URLEncoder.encode("UTF-8"));
            // 设置上传文件的长度。如超过此长度,则上传文件会被截断,上传的文件长度为设置的长度。如小于此长度,则为上传文件的实际长度。
            // meta.setContentLength(content.length());
            // 设置内容被下载时网页的缓存行为。
            // meta.setCacheControl("Download Action");
            // 设置缓存过期时间,格式是格林威治时间(GMT)。
            // meta.setExpirationTime(DateUtil.parseIso8601Date("2025-10-12T00:00:00.000Z"));

            // 设置Header。
            // meta.setHeader("yourHeader", "yourHeaderValue");

            // 上传文件。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()), meta);

            // 验证URL访问是否直接下载。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000);
            GeneratePresignedUrlRequest signRequest = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET);
            signRequest.setExpiration(expiration);
            URL signedUrl = ossClient.generatePresignedUrl(signRequest);
            System.out.println(signedUrl);

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

相关文档