【问题标题】:Upload to Amazon S3 from public URL从公共 URL 上传到 Amazon S3
【发布时间】:2021-04-27 02:28:18
【问题描述】:

我想使用AWS iOS SDK 将图像直接从公共 url 上传到 S3 存储桶。

我的目标是避免下载然后上传图像,这显然会更慢。 我试图天真地将 URL 传递给AWSS3TransferUtility.uploadFile,如下所示:

import AWSCore
import AWSS3

// ...

AWSS3TransferUtility.register(
    with: AWSServiceManager.default().defaultServiceConfiguration!,
    transferUtilityConfiguration: AWSS3TransferUtilityConfiguration(),
    forKey: "foo"
)

let utility = AWSS3TransferUtility.s3TransferUtility(forKey: "foo")!
let imageURL = URL(string: "https://via.placeholder.com/150/")!

utility
    .uploadFile(
        imageURL,
        bucket: "<bucket name>",
        key: "bar.jpeg",
        contentType: "image/jpg",
        expression: nil,
        completionHandler: nil)
    .continueWith {
        if let error = $0.error {
            print("Error: \(error.localizedDescription)")
        }
        return nil
    }

但它似乎只接受本地文件的url并返回错误

操作无法完成。 (com.amazonaws.AWSS3TransferUtilityErrorDomain 错误 4。)

知道这是否可行以及如何实现?

【问题讨论】:

  • S3 无法为您下载。在上传到 S3 之前,您必须将其下载到内存或磁盘。
  • 太可惜了,谢谢您的评论
  • 您可能会编写一个简单的 Lambda 函数,您的 iOS 客户端可以将源 URL 和目标 S3 密钥发送到该函数,该 Lambda 函数会为您将源文件流式传输到 S3。可以直接调用,也可以通过 API Gateway 调用。如果您真正想要做的是避免通过您的 iOS 应用程序和运行它的移动设备传输源文件,这可能会有所帮助。
  • 好主意,我会试试看 :)

标签: ios swift amazon-web-services amazon-s3 file-upload


【解决方案1】:

基于@jarmod 的想法,我可以使用 Lambda(此处简化):

const https = require('https');
const AWS = require('aws-sdk');

const s3 = new AWS.S3();

function loadImage(url) {
  return new Promise((resolve, reject) => {
    https.get(url, (resp) => {
      if(resp.statusCode > 200) {
          reject('The image could not be loaded (HTTP ' + resp.statusCode + ')');
      }
      
      resp.setEncoding('binary');
      let chunks = [];

      resp.on('data', (chunk) => {
        chunks.push(Buffer.from(chunk, 'binary'));
      });
      resp.on('end', () => {
        let binary = Buffer.concat(chunks);
        resolve(binary);
      });
      
    }).on("error", (err) => {
      console.log("Error: " + err.message);
      reject(err);
    });
  });
}


exports.handler = async (event, context, callback) => {
  try {
    const url = ...;
    const bucket = ...;
    const key = ...;

    const buffer = await loadImage(url);

    const destparams = {
        Bucket: bucket,
        Key: key,
        Body: buffer,
        ContentType: "image"
    };
    await s3.putObject(destparams).promise();
    
    return "OK";
  } catch(error) {
    return error;
  }
};

使用AWSLambda 调用 Lambda 非常简单:

let lambda = AWSLambdaInvocationRequest()!
lambda.functionName = // Lambda name
lambda.invocationType = .requestResponse
let parameters: [String: Any] = [:] // Parameters to pass to the lambda
let payload = try! JSONSerialization.data(withJSONObject: parameters, options: []) 
lambda.payload = payload

AWSLambda.default().invoke(lambda) { response, error in
    //...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-28
    • 2014-12-23
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    相关资源
    最近更新 更多