添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在 Web 和移动应用程序中,为用户提供上传数据的功能是很常见的。您的应用程序可能允许用户上传 PDF 和文件、照片或视频等媒体。每个现代 Web 服务器技术都有允许此功能的机制。通常,在基于服务器的环境中,该过程遵循此流程:

  • The user uploads the file to the application server.
  • The application server saves the upload to a temporary space for processing.
  • The application transfers the file to a database, file server, or object store for persistent storage.
  • 虽然该过程很简单,但它可能会对繁忙应用程序中的 Web 服务器的性能产生显着的副作用。媒体上传通常很大,因此传输这些媒体可能会占用大量的网络 I/O 和服务器 CPU 时间。您还必须管理传输状态以确保成功上传整个对象,并管理重试和错误。

    这对于具有尖峰流量模式的应用程序具有挑战性。例如,在专门发送节日问候的 Web 应用程序中,它可能仅在节假日前后遇到大部分流量。如果成千上万的用户尝试在同一时间上传媒体,这需要您横向扩展应用服务器并确保有足够的网络带宽可用。

    通过将这些文件直接上传到 Amazon S3,您可以避免通过您的应用程序服务器代理这些请求。这可以显着减少网络流量和服务器 CPU 使用率,并使您的应用程序服务器能够在繁忙时段处理其他请求。 S3 还具有高可用性和持久性,使其成为用户上传的理想持久存储。

    无服务上传到 S3

    当您直接上传到 S3 存储桶时,您必须首先从 Amazon S3 服务请求签名 URL。然后,您可以使用签名 URL 直接上传。这是您的应用程序前端的两步过程:

  • Call an Amazon API Gateway endpoint, which invokes the s3-presigned-url Lambda function. This gets a signed URL from the S3 bucket.
  • Directly upload the file from the application to the S3 bucket.
  • 我们使用 AWS SAM 来部署。

    git clone https://github.com/wangzan18/s3-presigned-urls.git
    cd s3-presigned-urls
    sam deploy --guided
    

    当部署完成之后,会输出一个 API 的终端节点:

    测试为两个步骤,第一步是通过请求获取一个预签名的 URL,第二步是向这个 URL PUT 一个图片。

    {"url": "https://s3-presigned-url-s3uploadbucket-41pnizqboni7.s3.amazonaws.com/3504834451.jpg?AWSAccessKeyId=ASIA5NAGHF6N7XQ72YIF&Signature=F5N0pymJB1J7ZpzgRRy6FLSX2BY%3D&content-type=image%2Fjpeg&x-amz-security-token=IQoJb3JpZ2luX2VjEHsaCWV1LXdlc3QtMSJIMEYCIQDiz5UvT4x5bMGbR4tyH4Af9jTiPeGaRRI%2F%2B24MrxasmwIhAPOFqy3A7hq5inu6Jbppc37xhnU3ygZn1FFTJeUhNpzYKsICCIT%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEQAhoMOTIxMjgzNTM4ODQzIgzb0OFdLrNq1xQ5rVMqlgJ5xuc80KvUyYF6FtRahmpkPVZkh8G4BG2SqFIDCXYRQJqOVpIKXplt3ct5DjZ%2FRAjosV85lnB4SxDBC6PvFaRFsRfmk6wmmJJBqNAr6hXOr%2FMnlpwe2dwC1ks7OP7xHmZqGnDjlNebLhs1x9osb61BYfmrwjJg18LqFAra1O%2FvoPJcxbWniHwYxuGAYacs4%2FcXMKKQadyOzrdv6w4g54PprSZhFL5QHVCWx2FpNIqnb7YOUDKF%2BydQMnFywuA6lnShOeZLAWjTExdYpZCIA0i0vcEBPDN2r86LYv%2BJqpTbb%2BDlnGlWAz6HxLwbWrvQ8vNOVt0coTeOqjmbdhdwFoonhv9oArH%2FnXk5yKPLYuKGolFAmuFdPzC6t4iIBjqZAapNMWAxIdJJdBojvErX2Ybnwr%2F2b%2B0aq%2BIQ0uQb3IfZeopurj00xI1L3VX0qFbP%2FMn2yhhTy6rjAVdBgBhXgBiw86dUdnke9e4wvw%2Bwuq3iREFIoKKRyYrZ4yjUoOKqaOHdFESfR6mASv7DER0HzYhemUf39NroIDGKPYqvJMfnKoXB4wWSuKdt2DXD8%2FVLhNoB%2FjIr4QOOYw%3D%3D&Expires=1627531724", "key": "3504834451.jpg"}
    

    拿到这个 URL,我们进行第二步,可以直接点击 URL:

    这里请求需要改为 PUT,在 Body 里面选择 binary 来上传图片,然后点击提交。

    可以看到请求成功,我们登录到 S3 看下图片上传如何:

    这里需要注意的是,因为我们的预签名 URL 的 Key 名称已经确定了,不管我们上传的图片是什么名称,最终结果都会显示 Key 的名称。

    在我的代码仓库里面,还有一个前端的页面,可以传到 S3,然后开放公网访问,提交图片。

    仅供简单测试,最重要的是后面移动应用如何对接。

    template.yaml

    这个文件是 SAM 最主要的配置文件,通过这一段参数,创建一个 HTTP API Gateway,允许一些请求参数。

      # HTTP API
      MyApi:
        Type: AWS::Serverless::HttpApi
        Properties:
          # CORS configuration - this is open for development only and should be restricted in prod.
          # See https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-httpapi-httpapicorsconfiguration.html   
          CorsConfiguration:
            AllowMethods:
              - GET
              - POST
              - DELETE
              - OPTIONS
            AllowHeaders:
              - "*"   
            AllowOrigins: 
              - "*"     
    

    下面这个资源比较重要一步,需要确保 Lambda 对 S3 有写的权限,并且事件驱动为 HTTP API Gateway。

      S3PreSignedUrlFunction:
        Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
        Properties:
          CodeUri: s3-presigned-url/
          Handler: app.lambda_handler
          Policies:
            - S3WritePolicy:
                BucketName: !Ref S3UploadBucket
            ## This permission allows the Lambda function to request signed URLs
            ## for objects that will be publicly readable. Uncomment if you want this ACL.
            # - Statement:
            #   - Effect: Allow
            #     Resource: !Sub 'arn:aws:s3:::${S3UploadBucket}/'
            #     Action:
            #       - s3:putObjectAcl
          Environment:
            Variables:
              UploadBucket: !Ref S3UploadBucket
          Runtime: python3.7
          Events:
            S3PreSignedApi:
              Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
              Properties:
                Path: /upload
                Method: get
                ApiId: !Ref MyApi 
    

    app.py

    整个申请预签名 URL 的函数比较简单,繁琐的功能 SDK 都已经封装好了,函数会自动生成一个随机的 Key,然后返回给请求者一个 URL,通过这个 URL 可以使用 PUT 请求上传参数

    import boto3
    import json
    import os
    import random
    def lambda_handler(event, context):
        bucket = os.environ.get('UploadBucket')
        key = random.getrandbits(32)
        url = boto3.client('s3').generate_presigned_url(
            ClientMethod='put_object', 
            Params={'Bucket': bucket, 
                    'Key': str(key) + '.jpg',
                    'ContentType': 'image/jpeg'},
            ExpiresIn=3600)
        return {
            "statusCode": 200,
            "body": json.dumps({
                "url": url,
                "key": str(key) + '.jpg'
    

    需要注意的是,因为我们要上传的是图片,所以需要在 Params 添加一个参数'ContentType': 'image/jpeg'

    参考文档:

    https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/PresignedUrlUploadObject.html

    欢迎大家扫码关注,获取更多信息

    java 对象列表取值转字符串列表 java对象转换成字符串
    JSON字符串和Java对象互转在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML、JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好,下面先看下JSON的格式。 JSON可以有两种格式一种是对象格式的另一种是数组对象JSON的对象格式的字符串: {"stuName