Configure Amazon S3, generate signed url by NodeJS and upload in React Native
1. Configure Amazon S3 (updating...)
2. Generate signed url by NodeJS
import AWS from 'aws-sdk'
import { getFileType } from './File'
const s3 = new AWS . S3 ( {
accessKeyId : process . env . AWS_S3_ACCESS_KEY_ID ,
secretAccessKey : process . env . AWS_S3_SECRET_ACCESS_KEY ,
useAccelerateEndpoint : process . env . ENV === 'prod' ,
region : process . env . AWS_S3_REGION
} )
const getFileUrl = ( key ) => {
return `http://${ process . env . AWS_S3_BUCKET_NAME } .s3-${ process . env . AWS_S3_REGION } .amazonaws.com/${ key } `
}
export const getS3PresignedUrl = ( key , expireSeconds = 60 * 60 , ACL = 'public-read' ) => {
if ( ! key ) return Promise . resolve ( null )
const fileType = getFileType ( key )
const params = {
Bucket : process . env . AWS_S3_BUCKET_NAME ,
Key : key ,
Expires : expireSeconds ,
ACL ,
ContentType : fileType
}
return new Promise ( ( resolve , reject ) => {
s3 . getSignedUrl ( 'putObject' , params , ( err , url ) => {
if ( err ) return reject ( err )
resolve ( {
signedUrl : url ,
contentType : fileType ,
fileUrl : getFileUrl ( envKey )
} )
} )
} )
}
import { mutate , GraphQLResponse } from '../helpers'
import { FetchBlobResponse } from 'rn-fetch-blob' ;
export const putFileToS3 = ( s3Url : string , uri : string , contentType : string ) => {
if ( ! s3Url || ! uri ) return Promise . reject ( new Error ( 'Empty data' ) )
return RNFetchBlob . fetch ( 'PUT' , s3Url , {
'Content-Type' : contentType
} , RNFetchBlob . wrap ( uri . replace ( 'file://' , '' ) ) )
}
export const getUploadSignedUrl = ( params : object = { } ) : Promise < GraphQLResponse > => {
return mutate ( MutationGetUploadSignedUrl , params )
}
export const uploadFile = async ( uri : string , onUploadProgress ?: ( props : object ) => any ) : Promise < GraphQLResponse > => {
if ( ! uri ) return Promise . resolve ( { success : false , data : 'file_empty' } )
const filename = getFilename ( uri )
if ( ! filename ) return Promise . resolve ( { success : false , data : 'file_name_cant_parse' } )
const { success , data } = await getUploadSignedUrl ( { filename } )
if ( ! success || ! data ) return Promise . resolve ( { success : false , data } )
const { contentType , signedUrl , fileUrl } = data . getUploadSignedUrl
return new Promise ( ( resolve , reject ) => {
putFileToS3 ( signedUrl , uri , contentType )
. uploadProgress ( ( written : number , total : number ) => {
if ( onUploadProgress ) {
onUploadProgress ( {
written,
total,
percent : Math . floor ( ( written / total ) * 100 )
} )
}
} ) . then ( ( res : FetchBlobResponse ) => {
const status = res . respInfo . status
if ( status === 200 ) return resolve ( { success : true , data : fileUrl } )
resolve ( { success : false } )
} ) . catch ( ( e : any ) => {
resolve ( { success : false , data : e } )
} )
} )
}