准备工作

更新时间:

本文介绍数据迁移之前的准备工作。

步骤一:上传列表文件

HTTP/HTTPS列表文件包括2类文件,1个manifest.json文件和1个或多个example.csv.gz文件,example.csv.gz为CSV压缩后的列表文件,单个example.csv.gz文件大小不超过50 MB,manifest.json为对CSV文件进行项配置的文件,支持上传至OSS或者AWS S3。

  1. 创建CSV列表文件

    在本地创建CSV格式的列表文件。列表文件最多支持8项,项与项之间用英文逗号(,)分隔;每行一个文件,文件之间用\n换行。各项的含义如下表所示。

    重要

    KeyUrl为必填项,其余项可以不填写。

    • 必填项

      名称

      是否必填

      描述

      说明

      Url

      在线迁移服务使用该链接的Get请求下载文件内容,Head请求获取文件元数据。

      说明

      Url需确保可以直接使用[curl --HEAD "$Url"]、[curl --GET "$Url"]等命令正常访问。在线迁移服务不支持重定向的$Url。

      UrlKey项必须要做编码处理,不做编码处理、包含特殊字符可能会导致文件迁移失败。

      • Url项的编码原则:在curl等命令行工具(非重定向)可正常访问的基础上,再进行一次Url编码。

      • Key项的编码原则:在您期望该文件在OSS上的ObjectName基础之上,再进行一次Url编码。

      重要

      UrlKey项做编码处理后,请务必进行以下内容确认,否则可能会导致文件迁移失败,或迁移到目的端的文件路径与您的预期不符。

      • 原字符串中的加号(+)已被编码成%2B。

      • 原字符串中的百分号(%)已被编码成%25。

      • 原字符串中的半角逗号(,)已被编码成%2C。

      例如,原字符串为a+b%c,d.file,编码后的字符串应该是a%2Bb%25c%2Cd.file

      Key

      迁移后的Object Name为prefix+文件名。

      假设您已生成未进行url编码的CSV文件,名称为plain_example.csv,该文件仅有两列,第一列为Url,这些Url可直接使用curl命令进行访问;第二列为Key,这些Key即为您期望该文件在OSS上的ObjectName。如下:

      https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/1354977961/p486238.jpg,assets/img/zh-CN/1354977961/p486238.jpg
      https://www.example-fake1.com/%E7%BC%96%E7%A0%81%E5%90%8E%E6%89%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E7%9A%84url/123.png,编码后才能访问的url/123.png
      https://www.example-fake2.com/无需编码即可访问的url/123.png,无需编码即可访问的url/123.png
      https://www.example-fake3.com/汉语/日本語にほんご/한국어/123.png,汉语/日本語にほんご/한국어/123.png
      重要

      请勿在Windows系统下使用自带的记事本软件编辑manifest.json或plain_example.csv,因为该软件可能会在文件内容起始3个字节添加特殊标记(0xefbbbf),从而可能引发在线迁移服务的解析异常。您可以在Linux或macOS下执行od -c plain_example.csv | less确认文件内容的起始3字节是否包含特殊标记。Windows系统下建议您使用Notepad++、Visual Studio Code等软件创建或编辑文件。

      如下Python编码示例代码将会按行读取plain_example.csv,并将编码后的结果输出到example.csv。代码仅供您参考,请根据实际需要进行适当修改。

      # -*- coding: utf-8 -*-
      import sys
      
      if sys.version_info.major == 3:
          from urllib.parse import quote_plus
      else:
          from urllib import quote_plus
          reload(sys)
          sys.setdefaultencoding("utf-8")
      
      # Source CSV file path.
      src_path = "plain_example.csv"
      # URL-encoded file path.
      out_path = "example.csv"
      
      # The sample CSV contains only two columns: url and key.
      with open(src_path) as fin, open(out_path, "w") as fout:
          for line in fin:
              items = line.strip().split(",")
              url, key = items[0], items[1]
              enc_url = quote_plus(url.encode("utf-8"))
              enc_key = quote_plus(key.encode("utf-8"))
              # The enc_url and enc_key vars are encoded format.
              fout.write(enc_url + "," + enc_key + "\n")
      

      运行上述代码,输出后的example.csv内容为:

      https%3A%2F%2Fhelp-static-aliyun-doc.aliyuncs.com%2Fassets%2Fimg%2Fzh-CN%2F1354977961%2Fp486238.jpg,assets%2Fimg%2Fzh-CN%2F1354977961%2Fp486238.jpg
      https%3A%2F%2Fwww.example-fake1.com%2F%25E7%25BC%2596%25E7%25A0%2581%25E5%2590%258E%25E6%2589%258D%25E8%2583%25BD%25E8%25AE%25BF%25E9%2597%25AE%25E7%259A%2584url%2F123.png,%E7%BC%96%E7%A0%81%E5%90%8E%E6%89%8D%E8%83%BD%E8%AE%BF%E9%97%AE%E7%9A%84url%2F123.png
      https%3A%2F%2Fwww.example-fake2.com%2F%E6%97%A0%E9%9C%80%E7%BC%96%E7%A0%81%E5%8D%B3%E5%8F%AF%E8%AE%BF%E9%97%AE%E7%9A%84url%2F123.png,%E6%97%A0%E9%9C%80%E7%BC%96%E7%A0%81%E5%8D%B3%E5%8F%AF%E8%AE%BF%E9%97%AE%E7%9A%84url%2F123.png
      https%3A%2F%2Fwww.example-fake3.com%2F%E6%B1%89%E8%AF%AD%2F%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AB%E3%81%BB%E3%82%93%E3%81%94%2F%ED%95%9C%EA%B5%AD%EC%96%B4%2F123.png,%E6%B1%89%E8%AF%AD%2F%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AB%E3%81%BB%E3%82%93%E3%81%94%2F%ED%95%9C%EA%B5%AD%EC%96%B4%2F123.png

    • 全部项

      名称

      是否必填

      说明

      Key

      迁移后的Object Name为prefix+文件名。

      Url

      在线迁移服务使用该链接的Get请求下载文件内容,Head请求获取文件元数据。

      Size

      迁移文件的大小,单位为字节(Byte)。

      StorageClass

      源Bucket的存储类型。

      LastModifiedDate

      待迁移文件的最后修改时间。

      ETag

      待迁移文件的ETag。

      HashAlg

      待迁移文件的Hash算法。

      HashValue

      待迁移文件的Hash值。

      说明

      以上示例中各项的顺序并非固定顺序,只需与manifest.json文件中fileSchema项顺序保持一致即可。

  2. 压缩CSV文件

    需要将CSV文件压缩为csv.gz文件,压缩方法如下:

    • 压缩单个文件

      例如dir目录下有一个文件example.csv,需执行如下压缩命令:

      gzip -c example.csv > example.csv.gz
      说明

      执行以上gzip命令压缩文件,不会保留源文件,如需保留源文件压缩,请执行命令gzip -c 源文件 > 源文件.gz

      压缩后得到.csv.gz文件。

    • 压缩多个文件

      例如dir目录下有三个文件example1.csv、example2.csv和 example3.csv,需执行如下压缩命令:

      gzip -r dir
      说明

      gzip命令不会打包目录,而是将指定目录下所有子文件分别进行压缩,且不会保留对应的源文件。

      压缩后在dir目录下得到三个文件example1.csv.gz、example2.csv.gz和example3.csv.gz。

  3. 创建manifest.json文件

    支持配置多个CSV文件,具体内容如下。

    • fileFormat:指定列表文件格式为CSV

    • fileSchema:对应CSV中文件项,请注意顺序。

    • files:

      • key:CSV文件在Bucket中的位置。

      • MD5checksum:16进制的MD5字符串,不区分大小写。例如:91A76757B25C8BE78BC321DEEBA6A5AD,如果不填写该值,则不会做校验。

      • size:列表文件大小。

    如下示例仅供您参考。

    {
        "fileFormat":"CSV",
        "fileSchema":"Url, Key",
        "files":[{
            "key":"dir/example1.csv.gz",
            "MD5checksum":"",
            "size":0
        },{
            "key":"dir/example2.csv.gz",
            "MD5checksum":"",
            "size":0
        }]
    }
  4. 您可以选择将创建的2类列表文件上传到OSS或AWS S3。

    • 将创建的2类列表文件上传到OSS的具体操作,请参见简单上传

      说明
      • 列表文件上传到OSS后,在线迁移服务会下载列表文件,并根据指定的地址迁移文件。

      • 新建任务时,请填写文件列表所在Bucket信息,列表路径的格式为列表所在目录/manifest.json,例如dir/manifest.json。

    • 将创建的2类列表文件上传到AWS S3。

      说明
      • 列表文件上传到AWS S3后,在线迁移服务会下载列表文件,并根据指定的地址迁移文件。

      • 新建任务时,请填写文件列表所在Bucket信息,列表路径的格式为列表所在目录/manifest.json,例如dir/manifest.json。

步骤二:创建目标存储空间

创建目标存储空间,用于存放迁移的数据。具体操作,请参见创建存储空间

步骤三:创建RAM用户并添加权限

重要
  • 该RAM用户用于迁移使用。在创建角色和进行迁移实施操作时,需要在该用户下进行操作。请尽量在源Bucket或者目的Bucket所在的主账号下创建该RAM用户。

  • 如果没有创建RAM用户,可以创建RAM用户并授权

登录主账号所在的RAM控制台,在用户页面,单击刚创建的RAM用户 操作 列的 添加权限

  1. 系统策略:管理OSS在线迁移服务的权限(AliyunOSSImportFullAccess)。

  2. 自定义权限策略:该策略必须包含ram:CreateRoleram:CreatePolicyram:AttachPolicyToRoleram:ListRoles权限。

    可参考创建自定义权限策略进行权限管理,以下是相关的权限策略脚本代码:

    {
        "Version":"1",
        "Statement":[
            {
                "Effect":"Allow",
                "Action":[
                    "ram:CreateRole",
                    "ram:CreatePolicy",
                    "ram:AttachPolicyToRole",
                    "ram:ListRoles"
                ],
                "Resource":"*"
            }
        ]
    }

步骤四:清单Bucket授权

请根据清单Bucket是否归属于本账号,完成相应的操作。

清单Bucket归属于本账号

  • 一键自动授权:

    强烈建议您使用迁移控制台授权角色进行一键授权操作,该操作请在迁移实施 > 步骤二 > 列表授权角色 中实施。

  • 手动授权:

    1、清单Bucket授权

    在角色页面,单击刚创建的RAM角色 操作 列的 新增授权

    • 自定义权限策略:该策略必须包含oss:List*oss:Get*权限。

    可参考创建自定义权限策略进行权限管理,以下是相关的权限策略脚本代码:

    说明

    以下权限策略仅供您参考,其中<myInvBucket>为本账号下的清单Bucket名称,请根据实际值替换。

    关于OSS权限策略的更多信息,请参见RAM Policy常见示例

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "oss:List*",
            "oss:Get*"
          ],
          "Resource": [
            "acs:oss:*:*:<myInvBucket>",
            "acs:oss:*:*:<myInvBucket>/*"
          ]
        }
      ]
    }

清单Bucket不归属于本账号

1、清单Bucket授权

  1. 使用清单Bucket所属账号登录OSS管理控制台

  2. 在左侧导航栏,单击 Bucket 列表,选择对应Bucket。

  3. 在左侧导航栏,选择权限控制 > Bucket 授权策略

  4. 在语法策略添加中,增加以下Bucket Policy,然后点击 编辑并保存

  • 自定义策略:

    授予RAM角色列举并读取该Bucket下所有资源的权限

    说明

    以下权限策略仅供您参考,其中<otherInvBucket>为 清单Bucket名称,<myuid>为 迁移控制台主账号UID,<otherUid>为 清单Bucket归属的主账号UID,<roleName>为上文创建的角色名称,请根据实际值替换。关于OSS权限策略的更多信息,请参见RAM Policy常见示例

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "oss:List*",
            "oss:Get*"
          ],
          "Principal": [
             "arn:sts::<myUid>:assumed-role/<roleName>/*"
          ],
          "Resource": [
            "acs:oss:*:<otherUid>:<otherInvBucket>",
            "acs:oss:*:<otherUid>:<othereInvBucket>/*"
          ]
        }
      ]
    }

步骤五:目的Bucket授权

请根据目的Bucket是否归属于本账号,完成相应的操作。

目的Bucket归属于本账号

  • 一键自动授权:

    强烈建议您使用迁移控制台自动授权角色进行一键授权操作,该操作请在迁移实施 > 步骤三 > 授权角色 中实施。

  • 手动授权:

    1、目的Bucket授权

    在角色页面,单击刚创建的RAM角色 操作 列的 新增授权

    • 自定义策略:该策略必须包含oss:List*oss:Get*oss:Put*oss:AbortMultipartUpload*权限。

    可参考创建自定义权限策略 进行权限管理,以下是相关的权限策略脚本代码:

    说明

    以下权限策略仅供您参考,其中<myDestBucket>为 本账号下的目的Bucket名称,请根据实际值替换。

    关于OSS权限策略的更多信息,请参见RAM Policy常见示例

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "oss:List*",
            "oss:Get*",
            "oss:Put*",
            "oss:AbortMultipartUpload"
          ],
          "Resource": [
            "acs:oss:*:*:<myDestBucket>",
            "acs:oss:*:*:<myDestBucket>/*"
          ]
        }
      ]
    }

目的Bucket不归属于本账号

1、目的Bucket授权

重要

在使用Bucket Policy按语法策略进行授权时,新添加的策略会覆盖已有的策略。请确保新添加的策略包含已有策略的内容,否则可能导致关联已有策略的操作失败。

  1. 使用目的Bucket所属账号登录OSS管理控制台

  2. 在左侧导航栏,单击 Bucket 列表,选择对应Bucket。

  3. 在左侧导航栏,选择 权限控制 > Bucket 授权策略。

  4. 按语法策略添加 中,增加自定义Bucket Policy,然后点击 编辑并保存

    • 授予RAM角色列举、读取、删除和写入该Bucket下所有资源的权限。

说明

以下权限策略仅供您参考,其中<otherDestBucket>填写 目的Bucket名称,<otherUid>填写 目的Bucket归属的主账号UID,<myUid>填写 迁移控制台主账号UID,<roleName>填写 上文创建的角色名称,请根据实际值替换。关于OSS权限策略的更多信息,请参见RAM Policy常见示例

{
  "Version": "1",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "oss:List*",
        "oss:Get*",
        "oss:Put*",
        "oss:AbortMultipartUpload"
      ],
      "Principal": [
         "arn:sts::<myUid>:assumed-role/<roleName>/*"
      ],
      "Resource": [
        "acs:oss:*:<otherUid>:<otherDestBucket>",
        "acs:oss:*:<otherUid>:<otherDestBucket>/*"
      ]
    }
  ]
}