首页 > 解决方案 > 如何使用 AWSS3TransferUtility 将带有用户元数据的音频文件上传到 S3

问题描述

我正在尝试允许用户将歌曲和元数据上传到 S3 文件夹。我无法上传音频(.mp3、.wav 等)。

用户信息存储在 DynamoDB 表中,但我希望将实际歌曲存储在 s3 文件夹中,并将两者连接起来。

使用以下代码,我似乎只能上传音频文件 S3 的名称,但没有实际数据......我似乎无法弄清楚。

import UIKit
import StoreKit
import AWSMobileClient
import AWSCognitoIdentityProvider
import AWSAppSync
import MediaPlayer
import AVKit
import AVFoundation
import MediaAccessibility
import MediaToolbox



class mediaUploadVC: UITableViewController, UINavigationControllerDelegate, MPMediaPickerControllerDelegate{

    fileprivate let BUCKETNAME = "newtbxbkt-newtbxeniv"


    var avMusicPlayer = MPMusicPlayerController.systemMusicPlayer
    var mpMediapicker: MPMediaPickerController!

    var mediaItems = [MPMediaItem]()

MPMusicPlayerController.systemMusicPlayer

    fileprivate let s3Service: S3Service = S3Service()

    override func viewDidLoad() {
        super.viewDidLoad()

    }



    @IBAction func pickSongBtn(_ sender: UIView) {

          mpMediapicker  = MPMediaPickerController.self(mediaTypes:MPMediaType.music)
          mpMediapicker .allowsPickingMultipleItems = false
          mpMediapicker .popoverPresentationController?.sourceView = sender as? UIView
          mpMediapicker .delegate = self

        self.present(mpMediapicker , animated: true, completion: nil)



    }

    func mediaPicker(_ mediaPicker: MPMediaPickerController, didPickMediaItems mediaItemCollection: MPMediaItemCollection) {

        avMusicPlayer.setQueue(with: mediaItemCollection)
        mediaPicker.dismiss(animated: true, completion: nil)

        avMusicPlayer.play()


    }


    @IBAction func uploadData(_ data: Any) {


        let data: Data = Data() // Data to be uploaded

        let expression = AWSS3TransferUtilityUploadExpression()
        expression.progressBlock = {(task, progress) in
            DispatchQueue.main.async(execute: {

                print("upload in progress")
                // Do something e.g. Update a progress bar.
            })
        }

        var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
        completionHandler = { (task, error) -> Void in
            DispatchQueue.main.async(execute: {
                if let _ = error {
                    print ("There was an error uploading files... \(error.debugDescription)")
                    print ("Let us check response \(String(describing: task.response?.allHeaderFields))")
                    print ("Let us check response \(String(describing: task.response?.debugDescription))")
                } else {
                    print("Completed uploading file...")
                }
            })
        }
        userAPI.getuserId { (userCognitoId) in
            let transferUtility = AWSS3TransferUtility.default()

            transferUtility.uploadData(data,
                                       bucket: self.BUCKETNAME,
                                       key: "protected/\(userCognitoId)/song1.mp3",
                contentType: "audio/mp3",
                expression: expression,
                completionHandler: completionHandler).continueWith {
                    (task) -> AnyObject? in
                    if let error = task.error {
                        print("Error: \(error.localizedDescription)")
                    }

                    if let _ = task.result {
                        // Do something with uploadTask.
                    }
                    return nil;
            }
        }
    }

    }

标签: swiftxcodeamazon-web-servicesaws-amplify

解决方案


let data: Data = Data()

This is the offending line.

At the moment, you are uploading an empty Data. You’ll need to convert the file contents you wish to upload into that Data and upload that.

Edit in response to comments:
To retrieve data from a file at a given URL on the system, you can call

let fileURL: URL = ... // get a reference to the URL 
if let data = try? Data(contentsOf: fileURL) {
    // now you have the data
}

There is another initializer for the AWSS3TransferUtilityUploadTask which takes the URL as an argument, which may be simpler in your case.

Getting the data of an MPMediaItem involves getting its assetURL, creating an AVAsset and using an AVAssetExportSession to write the data to a URL on the system (usually in the Temporary directory).

There are other posts here which go into more detail of how to export MPMediaItem asset data, which you should be able to easily search for.

iOS limits you to accessing only files contained in the directories of your application (or application group) sandbox, so don't expect you will be able to get just any data from the device.


推荐阅读