I am using Meteor and React JS. I also added Meteor Files.
https://github.com/VeliovGroup/Meteor-Files
By using this code,
this.Images = new FilesCollection({collectionName: 'Images'});
export default class Logo extends TrackerReact(React.Component){
constructor(){
...
Meteor.subscribe('files.images.all');
}
uploadLogo(e){
if (e.currentTarget.files && e.currentTarget.files[0]) {
// We upload only one file, in case
// there was multiple files selected
var file = e.currentTarget.files[0];
if (file) {
var uploadInstance = Images.insert({
file: file,
streams: 'dynamic',
chunkSize: 'dynamic',
transport: 'http'
}, false);
uploadInstance.on('start', function() {
//template.currentUpload.set(this);
});
uploadInstance.on('end', function(error, fileObj) {
if (error) {
alert('Error during upload: ' + error.reason);
} else {
console.log("done");
alert('File "' + fileObj.name + '" successfully uploaded');
}
});
uploadInstance.start();
}
}else{
console.log("error");
}
}
render(){
...
<input type="file" id="fileinput" onChange={this.uploadLogo.bind(this)} />
}
I am able to upload the file but I don't see any files in my directory.
Here is my publish.js,
this.Images = new Meteor.Files({
debug: true,
collectionName: 'Images',
allowClientCode: false, // Disallow remove files from Client
onBeforeUpload: function (file) {
// Allow upload files under 10MB, and only in png/jpg/jpeg formats
if (file.size <= 1024*1024*10 && /png|jpg|jpeg/i.test(file.extension)) {
return true;
} else {
return 'Please upload image, with size equal or less than 10MB';
}
}
});
Meteor.publish('files.images.all', function () {
return Images.find().cursor;
});
How can I display the image? How can I limit the user to upload files that are only images?
For me, their API Docs is not rich. I can't understand what the things they are talking in their docs.
By default uploaded files are stored in the file system. Read the FAQ:
Where are files stored by default?: by default if config.storagePath
isn't passed into Constructor it's equals to assets/app/uploads and
relative to running script:
On development stage:
yourDevAppDir/.meteor/local/build/programs/server
Note: All files
will be removed as soon as your application rebuilds or you run meteor
reset. To keep your storage persistent during development use an
absolute path outside of your project folder, e.g. /data directory.
On production: yourProdAppDir/programs/server
So you need to set a location with config.storagePath
Related
I'm using googleapis to upload different files to the Google Drive. The scenario is:
User provides a document and it's information through my REST API (I'm using NodeJS).
The REST API creates the directory that will contain the document, if it's not already exist.
The REST API uploads the document to that directory.
The structure of the drive is:
/root/documents/$type/$new_document
where $type is one of the user's provided fields and the $new_document is the document that was provided by the user.
The way I connect:
oauth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
drive_instance = google.drive({
version: 'v3',
auth: oauth2Client,
});
I figured how to upload the document to root folder of the Google Drive:
}
try {
const response = await drive.files.create({
requestBody: {
name: file.name,
mimeType: file.mimetype,
},
media: {
mimeType: file.mimetype,
body: file.data,
},
});
console.log(response.data);
} catch (error) {
console.log(error.message);
}
What I'm struggling is:
How to create the directory /root/documents/$type if it's not already existing?
How to upload the $new_document to /root/documents/$type?
For the second question, I know that the docs provide an option of parents[] that will contain all the folder IDs. but then, how can I get the folder ID of /root/documents/$type? Is there someway to combine the steps (like maybe mkdir -p for the directories or creating the directory will return the ID of the directory).
1. Try found folder you need via drive.files.list() method
You need set filter. Example:
add 'q': "..." in requestBody to search what you need
use "name = 'Some Folder Name'" to search by name
use "mimeType = 'application/vnd.google-apps.folder'" to search only folders
Thus, combine via and:
'q': "name = 'Some Folder Name' and mimeType = 'application/vnd.google-apps.folder'" to find all folders with name you chose
const folderName = 'Some Folder Name'
gapi.client.drive.files
.list({
'q': "name = 'Some Folder Name' and mimeType = 'application/vnd.google-apps.folder'",
'pageSize': 1000,
'fields': "files(id, name, parents)"
})
.then((response) => {
const files = response.result.files;
if (files.length > 0) {
handleSearchResult(files)
} else {
createFolder()
}
console.log(total / (1024*1024*1024))
});
About handleSearchResult() or createFolder:
It maybe more than 1 file. So you can find necessary root getting files[i].parents . That's why I added parents in 'fields': "files(id, name, parents)". https://developers.google.com/drive/api/v3/reference/files
Also you can add searching rule e.g. 'parents contain "..."''
https://developers.google.com/drive/api/v3/search-files
If search brings 0 files result so just create folder by yourself. You can create path\directory step-by step. Create first folder in drive root and remember id. After that create second folder and add in requestBody parentId that equal first folder id. And etc... Btw you can use almost the same logic to search.
2. Create folder if its necessary
Example:
// name = 'Folder Name',
// parents = ['some-parent1-id', 'some-parent2-id', ...]
function createFolder(name, parents) {
const fileMetadata = {
'name' : name,
'mimeType' : 'application/vnd.google-apps.folder',
'parents': parents
};
gapi.client.drive.files
.create({
resource: fileMetadata,
}).then((response) => {
switch(response.status){
case 200:
const file = response.result;
console.log('Created Folder Id: ' + file.id);
break;
default:
console.log('Error creating the folder, '+response);
break;
}
});
}
3. Upload file with setted parents
you should add parents = ['id-of-folder'] in requestBody
Read more in Google Drive API - Files: create
I hope it will help at least a bit:) Keep it up!
You can upload a folder inside a folder using the follow method
You should have the id of the folder you want to store the new folder in (can be extracted using nodejs api or by opening the folder and looking at the characters after last / in the url)
Use a special mimetype reserved for folders in google drive ( application/vnd.google-apps.folder )
considering your example
drive.files.create({
requestBody:{
name:"SomeFolder",
mimeType:"application/vnd.google-apps.folder"
},(error,folder)=>{
console.log(folder.data.id);
drive.files.create:({
requestBody:{
name:"SomeFolderInsideAFolder",
mimeType:"application/vnd.google-apps.folder"
},
parents:[folder.data.id]
})
})
})
You can even easily create a recursively uploading folder function by combining file upload and folder upload which can upload a whole folder
I have a project where it uses Filepond to upload files and I need it to load file from server.
I already follow the docs but It doesn't work. The Filepond gives error Error during load 400 and it even doesn't send the request to load the file from server
This is my javascript
let pond = FilePond.create(value, {
files: [
{
// the server file reference
source: 'e958818e-92de-4953-960a-d8157467b766',
// set type to local to indicate an already uploaded file
options: {
type: 'local'
}
}
]
});
FilePond.setOptions({
labelFileProcessingError: (error) => {
return error.body;
},
server: {
headers: {
'#tokenSet.HeaderName' : '#tokenSet.RequestToken'
},
url: window.location.origin,
process: (fieldName, file, metadata, load, error, progress, abort) => {
// We ignore the metadata property and only send the file
fieldName = "File";
const formData = new FormData();
formData.append(fieldName, file, file.name);
const request = new XMLHttpRequest();
request.open('POST', '/UploadFileTemp/Process');
request.setRequestHeader('#tokenSet.HeaderName', '#tokenSet.RequestToken');
request.upload.onprogress = (e) => {
progress(e.lengthComputable, e.loaded, e.total);
};
request.onload = function () {
if (request.status >= 200 && request.status < 300) {
load(request.responseText);
}
else {
let errorMessageFromServer = request.responseText;
error('oh no');
}
};
request.send(formData);
},
revert: "/UploadFileTemp/revert/",
load: "/UploadFileTemp/load"
}
})
This is my controller
public async Task<IActionResult> Load(string p_fileId)
{
//Code to get the files
//Return the file
Response.Headers.Add("Content-Disposition", cd.ToString());
Response.Headers.Add("X-Content-Type-Options", "nosniff");
return PhysicalFile(filePath, "text/plain");
}
NB
I already test my controller via postman and it works. I also check the content-disposition header
I'd advise to first set all the options and then set the files property.
You're setting the files, and then you're telling FilePond where to find them, it's probably already trying to load them but doesn't have an endpoint (yet).
Restructuring the code to look like this should do the trick.
let pond = FilePond.create(value, {
server: {
headers: {
'#tokenSet.HeaderName': '#tokenSet.RequestToken',
},
url: window.location.origin,
process: (fieldName, file, metadata, load, error, progress, abort) => {
// your processing method
},
revert: '/UploadFileTemp/revert',
load: '/UploadFileTemp/load',
},
files: [
{
// the server file reference
source: 'e958818e-92de-4953-960a-d8157467b766',
// set type to local to indicate an already uploaded file
options: {
type: 'local',
},
},
],
});
I'm trying to download a file (uploaded before in a swift container (openstack)) when I click on the link on my webpage interface.
The file is found when I display "res" but it's not downloaded (with my browser : "Fail = No File") and and I don't know why .. Should I use "html.response" ?
ps: interceptDownload is used by the "ostrio:file" package.
I'm using this code :
interceptDownload(http, image, versionName) {
var options = {
container: 'openstack',
remote: 'logo.png'
};
var stream = client.download(options, function(err, res) {
if(err) {
console.log(err);
} else {
console.log(res);
}
}).pipe(fs.createWriteStream('file.txt'));
},
I just want my app download a file from the server by using react-native-fetch-blob. The problem is, where do the file stored? I just console.log the callback from react-native-fetch-blob and got this object
React-native-fetch-blob object callback
this is my code
alert("downloading");
RNFetchBlob
.config({
useDownloadManager : true,
fileCache : true
})
.fetch('GET', 'http://fontawesome.io/assets/font-awesome-4.7.0.zip', {})
.then((res) => {
console.log(res);
alert("Download");
alert('The file saved to ', res.path());
})
Any solution?
To download a file directly with rn-fetch-blob, you need to set fileCache as true.
btw, react-native-fetch-blob is not maintained anymore, use rn-fetch-blob instead
document of download file directly
RNFetchBlob
.config({
// add this option that makes response data to be stored as a file,
// this is much more performant.
fileCache : true,
})
.fetch('GET', 'http://www.example.com/file/example.zip', {
//some headers ..
})
.then((res) => {
// the temp file path
console.log('The file saved to ', res.path())
})
function downloadFile(url,fileName) {
const { config, fs } = RNFetchBlob;
const downloads = fs.dirs.DownloadDir;
return config({
// add this option that makes response data to be stored as a file,
// this is much more performant.
fileCache : true,
addAndroidDownloads : {
useDownloadManager : true,
notification : false,
path: downloads + '/' + fileName + '.pdf',
}
})
.fetch('GET', url);
}
use this answer it will work for sure
I am using it and it works perfectly.
You just need to get the path like this.
var filePath = res.path();
this is where your file is stored.
I am using a node s3 client (https://github.com/andrewrk/node-s3-client#clientdownloaddirparams) to sync an entire directory from S3 to a local directory.
As per the documentation, my code is as follows:
var s3 = require('s3');
var client = s3.createClient({
s3Options: {
accessKeyId: Config.accessKeyId,
secretAccessKey: Config.secretAccessKey
}
});
var downloader = client.downloadDir({
localDir: 'images/assets',
deleteRemoved: true,
s3Params: {
Bucket: Config.bucket,
Prefix: Config.bucketFolder
}
});
downloader.on('error', function(err) {
console.error("unable to download: ", err);
});
downloader.on('progress', function() {
console.log("progress", downloader.progressMd5Amount, downloader.progressAmount, downloader.progressTotal);
});
downloader.on('end', function(data) {
console.log("done downloading", data);
});
This begins syncing and the folder begins downloading, but eventually returns this:
progress 0 0 0
...
progress 1740297 225583 5150000
unable to download: { Error: EISDIR: illegal operation on a directory, open 'images/assets'
at Error (native)
errno: -21,
code: 'EISDIR',
syscall: 'open',
path: 'images/assets' }
The directory does indeed exist. I've tried moving directory location, path, etc, but nothing seems to do the trick. I have researched this error and have found out that it occurs when you try to open a file, but the path given is a directory. Not sure why this s3-client is trying to open a file instead of a directory. Any help or advice would be awesome. Thanks!
I just determined that download speeds were causing this issue. Unfortunately, I was on a network with .5 up and down. I just switched over to 25/10 and its working fine.
Remember that in S3, you can create a directory that has the same name as a file. Based on the error you're getting, I would say that in S3 you have a file named images and a folder named images. This would be illegal on the file system but not in S3.
Use getS3Params function to resolve this :
getS3Params: function getS3Params(localFile, s3Object, callback) {
if (path.extname(localFile) === '') { callback(null, null); }
else { callback(null, {}); }
}
https://github.com/andrewrk/node-s3-client/issues/80