通过浏览器使用自定义域名访问OSS上存储的文件时,如果您的浏览器支持预览所选的文件格式,则OSS将直接预览,而非下载所选的文件。本文介绍如何配置通过自定义域名访问OSS文件时,以附件形式下载文件。

使用OSS控制台

  1. 登录OSS管理控制台
  2. 单击Bucket列表,然后单击目标Bucket名称。
  3. 在左侧导航栏,选择文件管理 > 文件列表
  4. 在目标Object右侧选择更多 > 设置HTTP头
  5. 设置HTTP头面板,将Content-Disposition设置为attachment或者attachment; filename="yourFileName",其他参数保留默认配置。
    • 设置为attachment,表示以保留原文件名的形式下载到浏览器指定路径。
    • 设置为attachment; filename="yourFileName",表示以自定义文件名的形式下载到浏览器指定路径。其中,yourFileName用于自定义下载后的文件名称,例如example.jpg。
  6. 单击确定

使用阿里云SDK

以Java SDK为例,示例如下:

import com.aliyun.oss.*;
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 Demo {
    public static void main(String[] args) throws Exception {

        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
        String objectName = "testfolder/exampleobject.txt";
        // 文件内容。
        String content = "Hello OSS";
        // 被下载时的文件名。
        String fileName = "测试文件.txt";

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

        try {
            // 创建上传文件的元信息,可以通过文件元信息设置HTTP header。
            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");
            // 设置内容被下载时的名称。如果包含有中文字符,需要进行URL编码。
            meta.setContentDisposition("attachment; filename="+ URLEncoder.encode(fileName,"UTF-8")+"; filename*=UTF-8''"+URLEncoder.encode(fileName,"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();
            }
        }
    }
}

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutObject