How to save the uploaded file to a folder? - rust

With this function I receive a file via graphql, How do I save the received content to a folder?
async fn single_upload(&self, ctx: &Context<'_>, file: Upload) -> FileInfo {
let mut storage = ctx.data_unchecked::<FileStorage>().lock().await;
println!("files count: {}", storage.len());
let entry = storage.vacant_entry();
let upload = file.value(ctx).unwrap();
let info = FileInfo {
id: entry.key().into(),
filename: upload.filename.clone(),
mimetype: upload.content_type,
};
entry.insert(info.clone());
info
}
I am using async-graphql and actix-web

Related

How to gzip a directory/folder using pako module in Nodejs?

I am trying to gzip my folder with the help of Pako library. I couldn't found any related content about it. Can someone explain me how to use pako to gzip directory. I am using it in my lambda function along with EFS.
let bundle = fs.readdirSync(tempDir);
let zippedFile = pako.gzip(bundle);
My folder location looks like this data/temp/
Error
TypeError: strm.input.subarray is not a function
You can use fs.readdirSync() to list files in the directory, then check the stat of each file before compressing it using fs.lstatSync(). I have tested this locally on my mac.
Then you can write the compressed file to your file system.
const fs = require('fs');
const pako = require('pako');
let files = fs.readdirSync('/tmp/');
let fileContent = '';
files.forEach(file => {
let path = '/tmp/' + file;
let stats = fs.lstatSync(path);
if (stats.isFile()) {
let data = fs.readFileSync(path);
fileContent += data;
}
});
let zippedFile = pako.gzip(fileContent);
const stream = fs.createWriteStream('/tmp/dir.gz');
stream.write(zippedFile);
stream.end();

Rust and Rocket: retrieve raw file content from form-data

Working with Rust and Rocket here. I have an endpoint to upload one file at a time with form-data:
use rocket::form::{Form, FromForm};
use rocket::fs::TempFile;
use std::ffi::OsStr;
use std::path::{Path};
use uuid::Uuid;
#[post("/file_upload", format = "multipart/form-data", data = "<form>")]
pub async fn file_upload(mut form: Form<Upload<'_>>) -> std::io::Result<String> {
// Get raw file
let file_name = form.file.raw_name().unwrap().dangerous_unsafe_unsanitized_raw().as_str();name
// Get extension of file name
let extension = Path::new(file_name).extension().and_then(OsStr::to_str).unwrap();
// Generate new UUID
let id: String = Uuid::new_v4().to_string();
// Build path to save file
let file_path = String::from("media/temp_files") + "/" + &id + "." + extension;
// Save file
form.file.persist_to(file_path).await?;
Ok(String::from("Ok"))
}
This works, but I am mixing persistence, business logic and http infrastructure in the same module.
I want to rely on Rocket only to retrieve the file stream and metadata (file name, size and content type), and pass it to another function that would be in charge or validation, image processing, etc.
I have access to the metadata, but I don't know how to retrieve the Buffered content from the TempFile struct.
// rocket-0.5.0-rc.2/src/fs/temp_file.rs
[…]
pub enum TempFile<'v> {
#[doc(hidden)]
File {
file_name: Option<&'v FileName>,
content_type: Option<ContentType>,
path: Either<TempPath, PathBuf>,
len: u64,
},
#[doc(hidden)]
Buffered {
content: &'v str,
}
}
[…]
I don't see any method returning it.Is there any method I'm missing to retrieve the raw file content? Or maybe there is a different struct/trait in Rocket to achieve this.

Xcode 13 Warning - [NSKeyedUnarchiver validateAllowedClass:forKey:]

I am using File Storage system for saving some data models confirming to Codable Protocol.
My Save function is as below:
func save<T: Encodable>(value: T, for key: String, on path: URL) throws {
let url = path.appendingPathComponent(key, isDirectory: false)
do {
try ANFileManager.createDirectoryAtPath(path: url.deletingLastPathComponent())
let archiver = NSKeyedArchiver(requiringSecureCoding: true)
archiver.outputFormat = .binary
try archiver.encodeEncodable(value, forKey: NSKeyedArchiveRootObjectKey)
archiver.finishEncoding()
// then you can use encoded data
try archiver.encodedData.write(to: url)
} catch {
throw StorageError.cantWrite(error)
}
}
My fetch function is as below:
func fetchValue<T: Decodable>(for key: String, from path: URL) throws -> T {
let url = path.appendingPathComponent(key)
let data = try Data(contentsOf: url)
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
unarchiver.decodingFailurePolicy = .setErrorAndReturn
guard let decoded = unarchiver.decodeDecodable(T.self, forKey:
NSKeyedArchiveRootObjectKey) else {
throw StorageError.notFound
}
unarchiver.finishDecoding()
if let error = unarchiver.error {
throw StorageError.cantRead(error)
}
else {
return decoded
}
}
Save and fetch are working fine but at runtime seeing some below warning in xcode console.
*** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving safe plist type ''NSString' (0x7fff863014d0) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework]' for key 'NS.keys', even though it was not explicitly included in the client allowed classes set: '{(
"'NSDictionary' (0x7fff862db9a0) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework]",
"'NSDate' (0x7fff862db798) [/Applications/Xcode_13.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework]"
)}'. This will be disallowed in the future.
What should be done to suppress the warning ?
The problem is the failure to require secure coding on the unarchiver:
https://developer.apple.com/documentation/foundation/nskeyedunarchiver/1410824-requiressecurecoding
But more broadly it is very odd to pass through a keyed archiver when Codable is already saveable directly.

Adding files to multiple folders in s3

I want to upload files which is present in tempFolder to 2 different buckets of s3.My code works as expected to upload multiple files to foldername1.
tempFolder has 8 files. i have upload all 8 to foldername1 and only last 2 files to my foldername2 in s3.
how can i add them.
function foo() {
let tempFolder = // folder path
return fs.readdirSync(tempFolder ).map((file) => {
let path = path.join(tempFolder , file);
let awsPath1 = // s3 bucket foldername1
let awsPath2 = // s3 bucket foldername2
let total = fs.statSync(path);
return s3Upload(awsPath1, () => fs.createReadStream(path), total.size)
.then(
() => {
s3Uploaded.push("https://aws.amazon.com/s3/bucketname/" + awsPath);
});
});
}

How to push the file to TFS using azure-devops-node-api library in NodeJS?

I'm trying to push the files to repository in Azure Repos. I'm using azure-devops-node-api library to connect and push the file to the repository. I'm beginner in NodeJS. Please find the below code. I'm not sure how to proceed further.
Please help!
const orgUrl = "https://dev.azure.com/orgname";
const azure = require('azure-devops-node-api');
var accessToken = "ACCESS_TOKEN";
var authHandler = azure.getPersonalAccessTokenHandler(accessToken);
var connection = new azure.WebApi(orgUrl, authHandler);
connection.getGitApi().then( gitapi1 => {
// I don't know how to use gitapi1 to commit and push the file
});
How to push the file to TFS using azure-devops-node-api library in NodeJS?
To push the files to repository in Azure Repos, we could use the git.createPush to push the code to the repository in Azure Repos. To use the git.createPush, we need to get the repostoryId. You can check below sample demo for some more details:
import * as azdev from "azure-devops-node-api";
import * as gitclient from "azure-devops-node-api/GitApi"
//import { GitRepository } from 'azure-devops-node-api/interfaces/TfvcInterfaces';
import { GitRepository, GitPush,GitCommitRef,GitCommit, GitChange, ItemContent, GitItem, GitRefUpdate } from 'azure-devops-node-api/interfaces/GitInterfaces';
let orgUrl = 'https://dev.azure.com/yourorg'
let repostories:GitRepository[];
let token: string = "PATTokne";//patToken
let project:string = 'projectName'
let repostoryName = 'repostoryName';
let authHandler = azdev.getPersonalAccessTokenHandler(token);
let connection = new azdev.WebApi(orgUrl, authHandler);
let file:string = 'C:\\Users\\xxx\\typescript-node\\test.png';
let refName:string = 'refs/heads/master';
var fs = require('fs');
var base64str = base64_encode(file);
console.log(base64str);
// function to encode file data to base64 encoded string
function base64_encode(filePath:string) {
// read binary data
var bitmap = fs.readFileSync(file);
// convert binary data to base64 encoded string
return new Buffer(bitmap).toString('base64');
}
async function run(filePath:string,refName:string,project:string,repostoryName:string)
{
let git:gitclient.IGitApi = await connection.getGitApi();
repostories = await git.getRepositories(project);
let gitrepo = repostories.find(element => element.name === repostoryName);
let repostoryId = gitrepo?.id;
let gitChanges:GitChange[] = [<GitChange>{
changeType:1,
newContent:<ItemContent>{content:base64str,contentType:1 }, //0-> RawText = 0, Base64Encoded = 1,
item:<GitItem>{
path:'/testUpdate.png'
}
}];
if(typeof(repostoryId) ==="string")
{
let ref = (await git.getRefs(repostoryId,project)).find(element => element.name === refName)
let refUpdates:GitRefUpdate[] = [<GitRefUpdate> {
name:ref?.name,
oldObjectId:ref?.objectId //get ref->object id
}];
let gitCommitRef:GitCommitRef[] = [
<GitCommitRef>{
changes:gitChanges,
comment:'Add a file'
}
]
let gitPush:GitPush = <GitPush>{
commits:gitCommitRef,
refUpdates:refUpdates,
repository:gitrepo
};
console.log(repostoryId)
await git.createPush(gitPush,repostoryId,project);
}
}
run(file,refName,project,repostoryName);
console.log("test");
Hope this helps.

Resources