AdonisJS multipart file uplaod - amazon-s3

public async create({ request, response }: HttpContextContract) {
try {
await request.multipart
.onFile(
'file',
{
size: '900mb',
},
async (file, reportChunk) => {
await Drive.putStream(`teste/${file.filename}`, file.file, {
contentType: file.file.type,
visibility: 'private',
})
}
)
.process()
return response.ok(request.multipart.state)
} catch (error) {
console.log(error)
}
}
Route receives multipart file and it does not work. Tryna do this https://docs.adonisjs.com/guides/direct-file-uploads with s3 driver but not working.

Related

Using aws-sdk to upload to DigitalOceans

I'm using aws-sdk to upload images to DigitalOceans bucket. On localhost it works 100% but production seems like the function goes on without an error but the file does not upload to the bucket.
I cannot figure out what is going on and can't think of a way to debug this. tried aswell executing the POST request with Postman multipart/form-data + adding file to the body of the request and it is the same for localhost, working, and production is not.
my api endpoint:
import AWS from 'aws-sdk'
import formidable from "formidable"
import fs from 'fs'
const s3Client = new AWS.S3({
endpoint: process.env.DO_SPACES_URL,
region: 'fra1',
credentials: {
accessKeyId: process.env.DO_SPACES_KEY,
secretAccessKey: process.env.DO_SPACES_SECRET
}
})
export const config = {
api: {
bodyParser: false
}
}
export default async function uploadFile(req, res) {
const { method } = req
const form = formidable()
const now = new Date()
const fileGenericName = `${now.getTime()}`
const allowedFileTypes = ['jpg', 'jpeg', 'png', 'webp']
switch (method) {
case "POST":
try {
form.parse(req, async (err, fields, files) => {
const fileType = files.file?.originalFilename?.split('.').pop().toLowerCase()
if (!files.file) {
return res.status(400).json({
status: 400,
message: 'no files'
})
}
if (allowedFileTypes.indexOf(fileType) === -1) {
return res.status(400).json({
message: 'bad file type'
})
}
const fileName = `${fileGenericName}.${fileType}`
try {
s3Client.putObject({
Bucket: process.env.DO_SPACES_BUCKET,
Key: `${fileName}`,
Body: fs.createReadStream(files.file.filepath),
ACL: "public-read"
}, (err, data) => {
console.log(err)
console.log(data)
})
const url = `${process.env.FILE_URL}/${fileName}`
return res.status(200).json({ url })
} catch (error) {
console.log(error)
throw new Error('Error Occured While Uploading File')
}
});
return res.status(200)
} catch (error) {
console.log(error)
return res.status(500).end()
}
default:
return res.status(405).end('Method is not allowed')
}
}

How to save pdf from an api response to file system in react native?

I'm receieving a blob from api and i want to save it as a pdf document to file system.But on saving I'm getting a file with size 0B in my mobile
Code
export const getParkingReciept = (bookindId) => {
return async function (dispatch, getState) {
try {
const TOKEN = getState().Auth.token;
const formdata = new FormData();
formdata.append("booking_id", bookindId);
RNFetchBlob.fetch(
'POST',
`${BASE_URL}parking-space/booking/receipt`,
{
'Accept': 'application/json',
'Authorization': `Bearer ${TOKEN}`,
'Content-Type': 'multipart/form-data'
},[
{ name : 'booking_id', data: bookindId.toString()}
]
)
.then(
response => {
console.log("response is ",response);
response.blob().then(res=>console.log(checkPermission(res,response.taskId)));
console.log("pdf base64 is ", response.base64());
}
).catch((error) => {
// error handling
console.log("Error", error)
}
);
}catch (e) {
if (e.response) {
console.log("error response is ", e.response);
} else if (e.request) {
console.log(e.request);
} else {
console.log('Error', e);
}
console.log(e.config);
}
}
const checkPermission=async (file,name) => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: "Cool Photo App Camera Permission",
message:
"Cool Photo App needs access to your camera " +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can write to external storage");
var path = RNFS.DownloadDirectoryPath + '/'+name+".pdf";
console.log("pdf being written is ",file);
RNFS.writeFile(path, file, 'utf8')
.then((success) => {
console.log('FILE WRITTEN!');
RNFetchBlob.fs.scanFile([ { path : path, mime : "application/pdf" } ])
// .then(() => {
// console.log("scan file success")
// })
// .catch((err) => {
// console.log("scan file error")
// })
})
.catch((err) => {
console.log(err.message);
});
} else {
console.log("permission denied");
}
} catch (err) {
console.warn(err);
}
};
reponse I get from fetch is
on calling blob() function of response what I get is
There is type Application/pdf there ,but in base 64 string does not start with JVBERi it starts with some SFRUU,Is that a valid pdf file?. What am I missing ? what am I doing wrong here?
This answer solves your problem , gives you detailed explanation about how to download files from a network request using rn fetch blob
https://stackoverflow.com/a/56890611/7324484
Once you downloaded the file or you can open the pdf directly using
https://www.npmjs.com/package/react-native-pdf

How to upload file from URL to S3 bucket (aws-sdk-js v3)?

I've tried the below code with no luck, which showing this error message:
(node:88634) UnhandledPromiseRejectionWarning: NotImplemented: A header you provided implies functionality that is not implemented
import { fromIni } from '#aws-sdk/credential-provider-ini'
import { S3Client, PutObjectCommand } from '#aws-sdk/client-s3'
import https from 'https'
import { Readable } from 'stream'
import awsConfig from './aws-exports'
const s3Client = new S3Client({
credentials: fromIni({ profile: 'default' }),
region: 'ap-northeast-1',
})
async function getFileFromUrl(url: string): Promise<Readable> {
return new Promise((resolve) => {
https.get(url, (response) => {
resolve(response)
})
})
}
async function upload(file: Readable) {
const uploadCommand = new PutObjectCommand({
Bucket: awsConfig.aws_user_files_s3_bucket,
Key: 'test.jpg',
Body: file,
ACL: 'public-read',
})
await s3Client.send(uploadCommand)
}
async function migrate() {
const file = await getFileFromUrl(
'https://example.com/logo.png'
)
await upload(file)
console.log('done')
}
migrate()
I could confirm that it's ok if I change the Body to a string...
Does anyone know how to do this correctly?
Thanks!
The problem here is that your getFileFromUrl function does not work, and AWS doesn't know how to handle the object you are handing it. You need to wait for the data event from https, like this:
async function getFileFromUrl (url) {
return new Promise((resolve) => {
https.get(url, (response) => {
response.on('data', (d) => {
resolve(d)
})
})
})
}

MERN and Amazon-s3 for file upload

How to post a file to Amazon S3 using node and react and save it path to mongoDB. with mongoose and formidable.
private async storeFile(file: { buffer: Buffer, fileId: string }): Promise<string> {
try {
const awsConfig = new AWS.Config(storageConfig);
const s3 = new AWS.S3(awsConfig);
let storageLink = undefined;
fs.readFile(file.buffer, (err, data) => {
if (err) {
throw err;
}
const params = {
Bucket:storageConfig.s3Bucket,
Key: `${storageConfig.s3Prefix}${file.fileId}`,
Body: data,
};
s3.upload(params, (s3Err: Error, s3Data: AWS.S3.ManagedUpload.SendData) => {
if (s3Err) {
throw s3Err;
}
storageLink = s3Data.Location;
});
});
return storageLink;
} catch (error) {
throw error;
}
}
In your Service file where you wanna call this function, update with record in collection
const storageLink = this.storeFile({ buffer, fileId });
const file = await file.updateOne({ _id: fileId }, {
status: fileStatus.UPLOADED, // just a flag
fileId: storageLink,
});

Ionic 2 clearing App cache on logout

My login function consists of a http request (an irrelevant one just for the check) with the entered credentials. This way I can resolve the request or get a rejection which I handle by not pushing the next component with the NavController onto the stack.
On logout, the credentials, which are saved in the Ionic Storage, are deleted. Now starts the problem: Any credentials that are saved now in the storage seems not to be used by the login request as the request doesn't throw an Auth exception. Only after clearing the Browser cache it works again.
This all happened by serving the app in a web browser and on the phone.
How is it possible to clear the App cache (not only the View/Component cache) with Ionic 2 to prevent this behaviour? There is no documentation or question concerning this problem existent at the moment.
Auth Service:
#Injectable()
export class AuthService {
HAS_LOGGED_IN = 'hasLoggedIn';
constructor(private storage: Storage) {
// this.rest = rest;
console.log('auth');
}
setCredentials(credentials) {
this.storage.set('username', credentials.username);
this.storage.set('password', credentials.password);
}
logout(): void {
this.storage.remove('username');
this.storage.remove('password');
this.storage.remove(this.HAS_LOGGED_IN);
}
hasLoggedIn() {
return this.storage.get(this.HAS_LOGGED_IN).then( value => {
console.log('hasLoggedIN value: ' + value);
return value === true;
});
}
}
Login Component:
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
model: any;
HAS_LOGGED_IN: string = 'hasLoggedIn';
constructor(private navCtrl: NavController,
private viewCtrl: ViewController,
private auth: AuthService,
private toastCtrl: ToastController,
private rest: RestService,
private storage: Storage) {
}
ionViewDidLoad() {
this.model = {};
}
ionViewWillEnter() {
this.viewCtrl.showBackButton(false);
this.displayTab(false);
}
login() {
console.log(this.model);
console.log('login() claled');
this.displayTab(true);
this.auth.setCredentials(this.model);
this.rest.getEntryPoint().then(data => {
console.log(data);
this.storage.set(this.HAS_LOGGED_IN, true);
this.navCtrl.push(OverviewPage);
}).catch(err => {
this.storage.set(this.HAS_LOGGED_IN, false);
console.log('Error:');
console.log(err);
this.navCtrl.push(LoginPage).then(response => {
console.log(response);
console.log(this.navCtrl);
console.log('pushed login 1');
});
});
}
validate(items: boolean) {
if (items) {
let toast = this.toastCtrl.create({
message: 'Passwort und Benutzername sind zwingend',
duration: 3000,
position: 'bottom',
});
toast.onDidDismiss(() => {
console.log('Dismissed toast');
});
toast.present();
}
}
private displayTab(display: boolean) {
let elements = document.querySelectorAll('.tabbar');
if (elements != null) {
Object.keys(elements).map((key) => {
elements[key].style.transform = display ? 'translateY(0)' : 'translateY(70px)';
});
}
}
}
Intercepting Http methods (this service is used in another service that makes the actual Rest calls):
#Injectable()
export class HttpInterceptorService {
constructor(#Inject(Http) private http: Http, private storage: Storage) {
this.http = http;
console.log('interceptor');
}
get(url) {
return new Promise((resolve, reject) => {
let headers = new Headers();
this.createAuthorizationHeader(headers).then(() => {
return this.http.get(url, {
headers: headers,
}).subscribe(data => {
resolve(data.json());
}, err => {
reject(err);
});
});
});
}
put(url: string, attributes?) {
return new Promise((resolve, reject) => {
let headers = new Headers();
this.createAuthorizationHeader(headers).then(() => {
return this.http.put(url, (attributes) ? attributes : {}, {
headers: headers,
}).subscribe(data => {
resolve(data.json());
}, err => {
reject(err);
});
});
});
}
post(url: string, data) {
return new Promise((resolve, reject) => {
let headers = new Headers();
this.createAuthorizationHeader(headers).then(() => {
return this.http.post(url, data, {
headers: headers,
}).subscribe(output => {
resolve(output.json());
}, err => {
reject(err);
});
});
});
}
private createAuthorizationHeader(headers: Headers): Promise<void> {
console.log('creating auth header');
return new Promise(resolve => {
this.storage.get('username')
.then( username => {
this.storage.get('password')
.then( password => {
headers.append('Authorization', 'Basic ' +
btoa(username + ':' + password));
resolve();
});
});
});
}
}
The other components are using hasLoggedIn() function to check if we are logged in or not when switching back to the App. If not logged in anymore (storage cleaned in any way) we get back to the LoginPage component.
The problem was a session header in the response that I somehow didn't see beforehand.
My solution is a simple Cookies clearing:
window.cookies.clear(function() {});