通过预先指定的URL将文件上载到AWS S3时,Javascript不工作

2024-04-25 20:19:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我生成一个预先指定的URL,用于通过Python支持的API将文件上载到aws3。一旦用户在浏览器中选择了文件(见下文),这个部分就会接收文件名信息,并返回一个带有基本URL和字段的JSON负载(见下文)。在

import logging
import boto3
from botocore.exceptions import ClientError


def create_presigned_post(bucket_name, object_name,
                          fields=None, conditions=None, expiration=3600):

    # Generate a presigned S3 POST URL
    s3_client = boto3.client('s3')
    try:
        response = s3_client.generate_presigned_post(bucket_name,
                                                     object_name,
                                                     Fields=fields,
                                                     Conditions=conditions,
                                                     ExpiresIn=expiration)
    except ClientError as e:
        logging.error(e)
        return None

    # The response contains the presigned URL and required fields
    return response

这是我从这个函数得到的JSON响应。(我修改/简化了一些值,但你明白了。)

^{pr2}$

这是我用来上传文件的HTML表单。我有一些普通的Javascript来跟踪表单的更改,并在更改时更新表单的URL_VALUE,以及每个表单项的{}(例如文件选择)。在

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>
  <body>
    <!-- Copy the 'url' value returned by S3Client.generate_presigned_post() -->
    <form action="URL_VALUE" method="post" enctype="multipart/form-data">
      <!-- Copy the 'fields' key:values returned by S3Client.generate_presigned_post() -->
      <input type="hidden" name="key" value="VALUE" />
      <input type="hidden" name="AWSAccessKeyId" value="VALUE" />
      <input type="hidden" name="policy" value="VALUE" />
      <input type="hidden" name="signature" value="VALUE" />
    File:
      <input type="file"   name="file" /> <br />
      <input type="submit" name="submit" value="Upload to Amazon S3" />
    </form>
  </body>
</html>

这个HTML表单本身工作得很好,但是我尝试添加一些Javascript(vanilla和JQuery),这样我就可以跟踪文件进度并禁用表单输入,直到上传完成。在

我无法让Javascript工作!!!

我尝试了很多例子(同样,香草JS和JQuery)。在

最近有没有人实施了这一点并能提供帮助?在


Tags: 文件nameimportnoneurl表单fieldsinput
3条回答

好了,找到了一个ridiculously simple普通JS示例,它很有用!在


$(document).ready(function () {
    var PRESIGNED_URL = ""

    $('input[type="file"]').change(function (e) {
        var fileName = e.target.files[0].name;

        var settings = {
            "async": true,
            "crossDomain": true,
            "url": "https://my_api.com",
            "method": "POST",
            "headers": {
                "Content-Type": "application/x-www-form-urlencoded",
            },
            "data": {
                "filename": fileName
            }
        }

        $.ajax(settings).done(function (response) {
            $("#filename").html(fileName)
            PRESIGNED_URL = response["url"]

            $("#form").attr("action", response["url"])
            $("#key").val(response["fields"]["key"])
            $("#AWSAccessKeyId").val(response["fields"]["AWSAccessKeyId"])
            $("#policy").val(response["fields"]["policy"])
            $("#signature").val(response["fields"]["signature"])
            $("#x-amz-security-token").val(response["fields"]["x-amz-security-token"])

            return
        });
    });

    $("#button").on("click", function (e) {
        var form = document.getElementById('form');
        var formData = new FormData(form);

        var xhr = new XMLHttpRequest();
        // Add any event handlers here...

        xhr.upload.addEventListener('progress', function(e) {
            var percent_complete = (e.loaded / e.total)*100;

            // Percentage of upload completed
            console.log(percent_complete);
        });
        xhr.onloadstart = function (e) {
            console.log("start")
        }
        xhr.onloadend = function (e) {
            console.log("end")
        }

        xhr.open('POST', PRESIGNED_URL, true);
        xhr.send(formData);

        $("#filename").html("")
    })
});



有如此多的密切变化,但这是完美的工作。在

(我相信这对很多人来说是显而易见的,但我只在必要时做前端开发…)

我相信你必须把AWS的秘密

"key": "some.txt",
    "AWSAccessKeyId": "ASI...",
    "x-amz-security-token": "Ag9o...",
    "policy": "eyJ...=",
    "signature": "jn...="

作为标题。在

您正在使用fetch库吗? 你能把JS代码发到吗?在

这甚至比你发布的更容易。在

fetch(yourSignedUrl, {
  method: 'PUT',
  body: file,
  headers: {
    'Content-Type': file.type
  }
}).then((res) => {
  if (!res.ok) {
    throw new Error(res.statusText);
  }
  return res.headers.get('ETag');
});

相关问题 更多 >