Amazon S3中是否有重命名文件和文件夹的功能?欢迎提出相关建议。


当前回答

我刚把它弄好了。你可以像这样使用AWS SDK:

use Aws\S3\S3Client;

$sourceBucket = '*** Your Source Bucket Name ***';
$sourceKeyname = '*** Your Source Object Key ***';
$targetBucket = '*** Your Target Bucket Name ***';
$targetKeyname = '*** Your Target Key Name ***';        

// Instantiate the client.
$s3 = S3Client::factory();

// Copy an object.
$s3->copyObject(array(
    'Bucket'     => $targetBucket,
    'Key'        => $targetKeyname,
    'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
));

http://docs.aws.amazon.com/AmazonS3/latest/dev/CopyingObjectUsingPHP.html

其他回答

正如Naaz所回答的,直接重命名s3是不可能的。

我附上了一个代码片段,它将复制所有的内容

代码正在工作,只需添加您的aws访问密钥和秘密密钥

这是我在代码中所做的

->复制源文件夹内容(嵌套子和文件夹)并粘贴到目标文件夹

->拷贝完成后,删除源文件夹

package com.bighalf.doc.amazon;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3ObjectSummary;

public class Test {

public static boolean renameAwsFolder(String bucketName,String keyName,String newName) {
    boolean result = false;
    try {
        AmazonS3 s3client = getAmazonS3ClientObject();
        List<S3ObjectSummary> fileList = s3client.listObjects(bucketName, keyName).getObjectSummaries();
        //some meta data to create empty folders start
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(0);
        InputStream emptyContent = new ByteArrayInputStream(new byte[0]);
        //some meta data to create empty folders end

        //final location is the locaiton where the child folder contents of the existing folder should go
        String finalLocation = keyName.substring(0,keyName.lastIndexOf('/')+1)+newName;
        for (S3ObjectSummary file : fileList) {
            String key = file.getKey();
            //updating child folder location with the newlocation
            String destinationKeyName = key.replace(keyName,finalLocation);
            if(key.charAt(key.length()-1)=='/'){
                //if name ends with suffix (/) means its a folders
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, destinationKeyName, emptyContent, metadata);
                s3client.putObject(putObjectRequest);
            }else{
                //if name doesnot ends with suffix (/) means its a file
                CopyObjectRequest copyObjRequest = new CopyObjectRequest(bucketName, 
                        file.getKey(), bucketName, destinationKeyName);
                s3client.copyObject(copyObjRequest);
            }
        }
        boolean isFodlerDeleted = deleteFolderFromAws(bucketName, keyName);
        return isFodlerDeleted;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

public static boolean deleteFolderFromAws(String bucketName, String keyName) {
    boolean result = false;
    try {
        AmazonS3 s3client = getAmazonS3ClientObject();
        //deleting folder children
        List<S3ObjectSummary> fileList = s3client.listObjects(bucketName, keyName).getObjectSummaries();
        for (S3ObjectSummary file : fileList) {
            s3client.deleteObject(bucketName, file.getKey());
        }
        //deleting actual passed folder
        s3client.deleteObject(bucketName, keyName);
        result = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

public static void main(String[] args) {
    intializeAmazonObjects();
    boolean result = renameAwsFolder(bucketName, keyName, newName);
    System.out.println(result);
}

private static AWSCredentials credentials = null;
private static AmazonS3 amazonS3Client = null;
private static final String ACCESS_KEY = "";
private static final String SECRET_ACCESS_KEY = "";
private static final String bucketName = "";
private static final String keyName = "";
//renaming folder c to x from key name
private static final String newName = "";

public static void intializeAmazonObjects() {
    credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_ACCESS_KEY);
    amazonS3Client = new AmazonS3Client(credentials);
}

public static AmazonS3 getAmazonS3ClientObject() {
    return amazonS3Client;
}

}

S3DirectoryInfo有一个MoveTo方法,它将把一个目录移动到另一个目录,这样移动的目录将成为另一个目录的子目录,其名称与原来的目录相同。

下面的扩展方法将一个目录移动到另一个目录,即移动的目录将成为另一个目录。它实际上所做的是创建新目录,将旧目录中的所有内容移到该目录中,然后删除旧目录。

public static class S3DirectoryInfoExtensions
{
    public static S3DirectoryInfo Move(this S3DirectoryInfo fromDir, S3DirectoryInfo toDir)
    {
        if (toDir.Exists)
            throw new ArgumentException("Destination for Rename operation already exists", "toDir");
        toDir.Create();
        foreach (var d in fromDir.EnumerateDirectories())
            d.MoveTo(toDir);
        foreach (var f in fromDir.EnumerateFiles())
            f.MoveTo(toDir);
        fromDir.Delete();
        return toDir;
    }
}

如果您想重命名s3文件夹中的许多文件,可以运行以下脚本。

    FILES=$(aws s3api list-objects --bucket your_bucket --prefix 'your_path' --delimiter '/'  | jq -r '.Contents[] | select(.Size > 0) | .Key' | sed '<your_rename_here>')
     for i in $FILES
     do
      aws s3 mv s3://<your_bucket>/${i}.gz s3://<your_bucket>/${i}
     done   

我所做的是创建一个新文件夹,并将旧的files对象移动到新文件夹。

s3中的文件夹结构有很多“问题”,似乎存储是扁平的。

我有一个Django项目,我需要重命名文件夹,但仍然保持目录结构不变,这意味着空文件夹也需要复制并存储在重命名的目录中。

aws cli很棒,但cp或sync或mv都没有将空文件夹(即以'/'结尾的文件)复制到新的文件夹位置,所以我使用boto3和aws cli的混合来完成任务。

或多或少我找到重命名目录中的所有文件夹,然后使用boto3将它们放在新位置,然后我用aws cli对数据进行cp,最后将其删除。

import threading

import os
from django.conf import settings
from django.contrib import messages
from django.core.files.storage import default_storage
from django.shortcuts import redirect
from django.urls import reverse

def rename_folder(request, client_url):
    """
    :param request:
    :param client_url:
    :return:
    """
    current_property = request.session.get('property')
    if request.POST:
        # name the change
        new_name = request.POST['name']
        # old full path with www.[].com?
        old_path = request.POST['old_path']
        # remove the query string
        old_path = ''.join(old_path.split('?')[0])
        # remove the .com prefix item so we have the path in the storage
        old_path = ''.join(old_path.split('.com/')[-1])
        # remove empty values, this will happen at end due to these being folders
        old_path_list = [x for x in old_path.split('/') if x != '']

        # remove the last folder element with split()
        base_path = '/'.join(old_path_list[:-1])
        # # now build the new path
        new_path = base_path + f'/{new_name}/'
        # remove empty variables
        # print(old_path_list[:-1], old_path.split('/'), old_path, base_path, new_path)
        endpoint = settings.AWS_S3_ENDPOINT_URL
        # # recursively add the files
        copy_command = f"aws s3 --endpoint={endpoint} cp s3://{old_path} s3://{new_path} --recursive"
        remove_command = f"aws s3 --endpoint={endpoint} rm s3://{old_path} --recursive"
        
        # get_creds() is nothing special it simply returns the elements needed via boto3
        client, resource, bucket, resource_bucket = get_creds()
        path_viewing = f'{"/".join(old_path.split("/")[1:])}'
        directory_content = default_storage.listdir(path_viewing)

        # loop over folders and add them by default, aws cli does not copy empty ones
        # so this is used to accommodate
        folders, files = directory_content
        for folder in folders:
            new_key = new_path+folder+'/'
            # we must remove bucket name for this to work
            new_key = new_key.split(f"{bucket}/")[-1]
            # push this to new thread
            threading.Thread(target=put_object, args=(client, bucket, new_key,)).start()
            print(f'{new_key} added')

        # # run command, which will copy all data
        os.system(copy_command)
        print('Copy Done...')
        os.system(remove_command)
        print('Remove Done...')

        # print(bucket)
        print(f'Folder renamed.')
        messages.success(request, f'Folder Renamed to: {new_name}')

    return redirect(request.META.get('HTTP_REFERER', f"{reverse('home', args=[client_url])}"))