I want t upload a csv file from my iOS App (written in Swift) to my amazon S3 bucket. To do this I'm using following code:
//Create
let fileName = "Export.csv"
let path = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
csvText = CreateCSVAccount()
do {
try csvText.write(to: path!, atomically: true, encoding: String.Encoding.utf32BigEndian)
//Prepare Upload
let uploadingFileURL = path
let uploadRequest = AWSS3TransferManagerUploadRequest()
let Bucketname = "mybucket/CSV"
uploadRequest?.bucket = Bucketname
uploadRequest?.key = "mycsvfile.csv"
uploadRequest?.body = uploadingFileURL!
//Upload File
transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error as NSError? {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error Contact uploading: \(String(describing: uploadRequest?.key)) Error: \(error)")
}
} else {
print("Error Contact uploading: \(String(describing: uploadRequest?.key)) Error: \(error)")
}
return nil
}
let uploadOutput = task.result
print("Upload complete for: \(String(describing: uploadRequest?.key))")
print("uploadOutput: \(String(describing: uploadOutput))")
return nil
})
} catch {
print("Failed to create file")
print("\(error)")
}
The problem is sometimes it works and sometimes I'm receiving the following error:
Message=You did not provide the number of bytes specified by the Content-Length HTTP header, NumberBytesExpected=412, Code=IncompleteBody, RequestId=075D1F5B0A377E89
Can somebody please help me?
Thank you very much in advance!
Add the contentLength header to your request.
That is:
uploadRequest?.contentLength = 1234
where 1234 is an NSNumber representing the number of bytes in body
Related
In my iOS app, I try to download a file from an AWS S3 bucket. Here is what I tried:
I initialize AWSMobileClient:
import AWSMobileClient
import AWSS3
let configuration = AWSServiceConfiguration(
region: AWSRegionType.EUCentral1,
credentialsProvider: AWSMobileClient.default())
AWSServiceManager.default().defaultServiceConfiguration = configuration
AWSMobileClient.default().initialize { (userState: UserState?, error: Error?) in
if (userState != nil)
{
print("Initialize OK : \(userState.debugDescription)")
}
if (error != nil)
{
print("Initialize error: \(String(describing: error))")
}
}
I got:
"initialize OK : Optional(AWSMobileClient.UserState.guest)"
Now I try to download a file:
let expression = AWSS3TransferUtilityDownloadExpression()
expression.progressBlock = {(task, progress) in DispatchQueue.main.async(execute: {
print("Progress : \(progress)")
})
}
let completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock = {
(task: AWSS3TransferUtilityDownloadTask, url: URL?, data: Data?, error: Error?) -> Void in
DispatchQueue.main.async(execute: {
print("End download 1")
})
}
let fileManager = FileManager.default
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("100.ogg")
let transferUtility: AWSS3TransferUtility = AWSS3TransferUtility.default()
transferUtility.download(
to: fileURL,
bucket: "my-s3-bucket",
key: "100.ogg",
expression: expression,
completionHandler: completionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error download : \(error)")
}
if let result = task.result {
print("Result : \(result.debugDescription)")
}
print("End download 2 : \(fileManager.fileExists(atPath: fileURL.absoluteString))")
return nil
}
I got:
"Result : <AWSS3TransferUtilityDownloadTask: 0x6000020bd4d0>
"End download 2 : false"
I don't get any progress, and I also don't get the "End download 1"
So basically, I dont get any error, but it does look like nothing has been downloaded. Also, on a side note, it works well with the Android version of my app, so it's very likely that there is an error in my code.
So what should I change to make it work?
Thanks.
My bad, the example above is actually working, But I had to:
change fileManager.fileExists(atPath: fileURL.absoluteString)) by fileManager.fileExists(atPath: fileURL.path))
check if file exists in the first completionHandler (where I wrote print("End download 1"))
TransferUtility works well when I upload the captured video file with its original format (.MOV) but when upload the converted file it becomes 0 a byte file.
After converting the file from .MOV to .MP4 I check that the file size isn't 0. Also I have to change the content type from movie/quicktime to video/mp4.
Is this the correct process?
Calling the uploading function
uploadToAWS(path: filePath, contentType: "video/mp4", key: videoname)
Function to convert the file
func exportVideo(inputurl: URL,
presetName: String = AVAssetExportPresetHighestQuality,
outputFileType: AVFileType = .mp4,
fileExtension: String = "mp4",
then completion: #escaping (URL?) -> Void)
{
let asset = AVAsset(url: inputurl)
let filename = filePath.deletingPathExtension().appendingPathExtension(fileExtension).lastPathComponent
outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename)
if let session = AVAssetExportSession(asset: asset, presetName: presetName) {
session.outputURL = outputURL
session.outputFileType = outputFileType
session.shouldOptimizeForNetworkUse = true
session.exportAsynchronously {
switch session.status {
case .completed:
completion(self.outputURL)
case .cancelled:
debugPrint("Video export cancelled.")
completion(nil)
case .failed:
let errorMessage = session.error?.localizedDescription ?? "n/a"
debugPrint("Video export failed with error: \(errorMessage)")
completion(nil)
default:
break
}
}
} else {
completion(nil)
}
}
Function for the uploading
func uploadToAWS(path: URL, contentType: String, key: String) {
exportVideo(inputurl: path, presetName: AVAssetExportPresetHighestQuality, outputFileType: .mp4, fileExtension: "mp4") { (outputURL) in
//here i checked that the file has not 0 bytes
do {
let resources = try outputURL?.resourceValues(forKeys:[.fileSizeKey])
let fileSize = resources?.fileSize!
print ("size of this video is \(fileSize)")
} catch {
print("Error: \(error)")
}
}
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = progressBlock
transferUtility.uploadFile(outputURL, bucket: bucket, key: key, contentType: contentType, expression: expression, completionHandler: completionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
DispatchQueue.main.async {
print("failed")
}
}
if let _ = task.result {
DispatchQueue.main.async {
print("Upload Starting!")
}
// Do something with uploadTask.
}
return nil;
}
}
Your upload (transferUtility.uploadFile(...)) currently starts as soon as exportVideo returns, which only guarantees that the AVAssetExportSession has been created, rather than waiting until it has finished. Move the upload logic inside the export completion and you should find that the upload operates on the completed export:
func uploadToAWS(path: URL, contentType: String, key: String) {
exportVideo(inputurl: path, presetName: AVAssetExportPresetHighestQuality, outputFileType: .mp4, fileExtension: "mp4") { (outputURL) in
//here i checked that the file has not 0 bytes
do {
let resources = try outputURL?.resourceValues(forKeys:[.fileSizeKey])
let fileSize = resources?.fileSize!
print ("size of this video is \(fileSize)")
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = progressBlock
transferUtility.uploadFile(outputURL, bucket: bucket, key: key, contentType: contentType, expression: expression, completionHandler: completionHandler).continueWith { (task) -> AnyObject? in
if let error = task.error {
print("Error: \(error.localizedDescription)")
DispatchQueue.main.async {
print("failed")
}
}
if let _ = task.result {
DispatchQueue.main.async {
print("Upload Starting!")
}
// Do something with uploadTask.
}
return nil
}
} catch {
print("Error: \(error)")
}
}
}
Can I upload pdf files into firebase using Swift?.
If it is possible please share me the code.
I'm using the below code
let proofRef = filesstorgRef.child(timestamp)
let uploadTask = proofRef.putData(data, metadata: nil, completion: { (metadata, error) in
if error != nil {
//print("Failed to upload image:", error)
return
}
if let fileUrl = metadata?.downloadURL()?.absoluteString {
completion(fileUrl)
}
})
uploadTask.observe(.progress) { (snapshot) in
if (snapshot.progress?.completedUnitCount) != nil {
print("ImageUploadingPerCent=== \(String(describing: snapshot.progress?.completedUnitCount))")
}
}
uploadTask.observe(.success) { (snapshot) in
print("ImageUploading Success")
}
uploadTask.observe(.failure) { (snapshot) in
LoadingView.sharedInstance.visible(visible: false)
print("ImageUploading failure")
}
thanks in advance
// Get the default app firebse storage reference
let FIRStorage = Storage.storage()
// reference of the storage
let storageRef = FIRStorage.reference()
// You have to get the file URL from disk or anywhere
let filePath = Bundle.main.path(forResource: "mypdf", ofType: "pdf")
let filePathURL = URL(fileURLWithPath: filePath!)
// Create a reference/Path on firebase database, where you want to upload your file
let fileRef = storageRef.child("firebase path with filename")
// from this you cant upload the file on fileRef path
let uploadTask = fileRef.putFile(from: filePathURL, metadata: nil) { metadata, error in
guard let metadata = metadata else {
// error!
return
}
let metadataSize = metadata.size
// get the download url of this file
fileRef.downloadURL { (url, error) in
guard let downloadURL = url else {
// error!
return
}
}
}
Try this code.
I am fetching multiple files (docs/pdfs) from iCloud/Dropbox to my iOS (Swift) app and trying to uploading them to AWS.
I have seen AWS documentation for uploading the files to AWS one by one (not multiple at a time).
I am trying to uploading multiple files same time to AWS.
I have array which contains multiple document/pdfs paths.
I have seen following code in AWS documentation.
let uploadingFileURL = URL(fileURLWithPath: "your/file/path/myTestFile.txt")
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.bucket = "myBucket"
uploadRequest.key = "myTestFile.txt"
uploadRequest.body = uploadingFileURL
transferManager.upload(uploadRequest).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if let error = task.error as? NSError {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error uploading: \(uploadRequest.key) Error: \(error)")
}
} else {
print("Error uploading: \(uploadRequest.key) Error: \(error)")
}
return nil
}
let uploadOutput = task.result
print("Upload complete for: \(uploadRequest.key)")
return nil
})
how to move forward on this task?
I am using google drive SDK for uploading CSV file. I used code given in google but error is coming
func create(){
let fileData = FileManager.default.contents(atPath: "FL_insurance_sample.csv")
let folderId: String = self.fileId!
let metadata = GTLRDrive_File.init()
metadata.name = "FL_insurance_sample"
metadata.mimeType = "application/vnd.google-apps.spreadsheet"
metadata.parents = [folderId]
let uploadParameters = GTLRUploadParameters(data: fileData! , mimeType: "text/csv")
uploadParameters.shouldUploadWithSingleRequest = true
let query = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)
query.fields = "id"
self.service.executeQuery(query, completionHandler: {(ticket:GTLRServiceTicket, object:Any?, error:Error?) in
if error == nil {
// print("File ID \(files.identifier)")
}
else {
print("An error occurred: \(error)")
}
})
}
It showing nil error on uploadParameters at fileData. Can anyone help me out.
Variable fileData is nil because you've passed the wrong file path. To get correct file path use:
guard let filePath = Bundle.main.path(forResource: "FL_insurance_sample", ofType: "csv") else {
print("No such file in bundle")
// handle situation
return
}
guard let fileData = FileManager.default.contents(atPath: filePath) else {
print("Can't read file")
// handle situation
return
}
// upload fileData