147 votes

Amazon S3 Modifier le nom de téléchargement du fichier

J'ai des fichiers stockés sur S3 avec un GUID comme nom de clé.

J'utilise une URL pré-signée pour le téléchargement comme suit API S3 REST

Je stocke le nom du fichier original dans ma propre base de données. Lorsqu'un utilisateur clique pour télécharger un fichier à partir de mon application web Je souhaite leur renvoyer leur nom de fichier original, mais actuellement, tout ce qu'ils obtiennent est un GUID. . Comment y parvenir ?

Mon application web est dans salesforce donc je n'ai pas beaucoup de contrôle pour faire des response.redirects tous télécharger le fichier sur le serveur web puis le renommer à cause des limitations du gouverneur.

Existe-t-il une redirection HTML, un meta refresh, un Javascript que je puisse utiliser ? Existe-t-il un moyen de changer le nom du fichier de téléchargement pour S3 (la seule chose à laquelle je pense est de copier l'objet sous un nouveau nom, de le télécharger, puis de le supprimer).

Je veux éviter de créer un bac par utilisateur car nous aurons beaucoup d'utilisateurs et il n'y a toujours pas de garantie que chaque fichier dans chaque bac aura un nom unique.

D'autres solutions ?

2voto

Chris Mcdonald Points 19

Il semble que :response_content_disposition ne soit pas documenté dans la méthode presigned_url. Voici ce qui a fonctionné pour moi

    signer = Aws::S3::Presigner.new
    signer.presigned_url(:get_object, bucket: @bucket, key: filename, 
    response_content_disposition: "attachment; filename =#{new_name}")

1voto

Udi Points 6298

Utilisation de python et de boto v2 :

    conn = boto.connect_s3(
        AWS_ACCESS_KEY_ID,
        AWS_SECRET_ACCESS_KEY,
        host=settings.AWS_S3_HOST,
    )
    b = conn.get_bucket(BUCKET_NAME)
    key = b.get_key(path)
    url = key.generate_url(
        expires_in=60 * 60 * 10,  # expiry time is in seconds
        response_headers={
            "response-content-disposition": "attachment; filename=foo.bar"
        },
    )

1voto

Siddhant_Jain10 Points 11

J'ai été confronté à un problème similaire. J'ai besoin de générer une url pré-signée pour télécharger un pdf depuis s3 mais avec un nom différent de celui présent dans le bucket s3. Ce problème a été résolu en utilisant :-

Utilisation de Python boto3

file_download_url = client.generate_presigned_url(
ClientMethod = "get_object",
ExpiresIn = 3600,
Params = {
    "Bucket": "s3_bucket_name",
    "Key": "s3_key",
    "ResponseContentDisposition": "attachment; filename=file_name.pdf",
    "ResponseContentType" : "application/pdf"
}

)

Référence :- https://github.com/boto/boto3/issues/356

0voto

mok Points 126

J'ai le même problème, je l'ai résolu en mettant l'en-tête http "content-disposition" lors de l'envoi du fichier sur S3, la version du SDK est AWS SDK for PHP 3.x. Voici la doc http://docs.amazonaws.cn/en_us/aws-sdk-php/latest/api-s3-2006-03-01.html#putobject

un morceau de mon code

    public function __construct($config) 
    {
        $this->handle = new S3Client([
            'credentials' => array(
                'key' => $config['key'],
                'secret' => $config['secret'],
            ),
            ...
        ]);

        ...
    }

    public function putObject($bucket, $object_name, $source_file, $content_type = false, $acl = 'public-read', $filename = '')
    {
        try {
            $params = [
                'Bucket'      => $bucket,
                'Key'         => $object_name,
                'SourceFile'  => $source_file,
                'ACL'         => $acl,
            ];

            if ($content_type) $params['ContentType'] = $content_type;
            if ($filename) $params['ContentDisposition'] = 'attachment; filename="' . $filename . '"';

            $result = $this->handle->putObject($params);

            ...
        }
        catch(Exception $e)
        {
            ...
        }
    }

0voto

Jha Nitesh Points 48

J'ai passé quelques heures à trouver cette solution.

const { CloudFront } = require("aws-sdk");
const url = require("url");

const generateSingedCloudfrontUrl = (path) => {
  const cloudfrontAccessKeyId = process.env.CF_ACCESS_KEY;
  const cloudFrontPrivateKey = process.env.CF_PRIVATE_KEY;
  const formattedKey = `${"-----BEGIN RSA PRIVATE KEY-----"}\n${cloudFrontPrivateKey}\n${"-----END RSA PRIVATE KEY-----"}`;
  const signer = new CloudFront.Signer(cloudfrontAccessKeyId, formattedKey);
  //  12 hours
  const EXPIRY_TIME = 43200000;

  const domain = process.env.CF_DOMAIN;
  const signedUrl = signer.getSignedUrl({
    url: url.format(`https://${domain}/${path}`),
    expires: Math.floor((Date.now() + EXPIRY_TIME) / 1000),
  });
  return signedUrl;
};

const fileName = "myFile.png";
  const result = generateSingedCloudfrontUrl(
    `originals/orgs/originals/MSP/1539087e-02b7-414f-abc8-3542ee0c8420/1644588362499/Screenshot from 2022-02-09 16-29-04..png?response-content-disposition=${encodeURIComponent(
      `attachment; filename=${fileName}`
    )
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X