In a meteor project I maintain there has been cause to look at moving away from gridfs as the backend to CollectionFS and moving towards s3.
One thing I would be keen to do is migrate images / files currently stored using the gridfs collections.
Has anyone attempted this before? I can't find any guides or even suggestions.
My thinking right now is along the lines of;
Create a new collection backed by s3
Iterate over old collection pushing the data into s3
Update code to point to new collection
Does this seem sound?
I just did this!
You're basically right, here's how I did it. Migration is a pretty easy process. I've gone from GridFS to S3.
1) By adding new FS.Store.S3("store_name",{}), CollectionFS automatically clones the meta data of existing files in the old store for your new store. But, all file sizes are zero in this new store.
Images = new FS.Collection("images", {
stores: [
new FS.Store.S3("s3images", {}),
new FS.Store.GridFS("images", {})
]
});
2) While you have both stores in place, you need to manually migrate the content using the piping as referenced here https://github.com/CollectionFS/Meteor-CollectionFS/wiki/How-to:-Convert-a-file-already-stored.
if(Meteor.isServer) {
Images.find().forEach(function (fileObj) {
var readStream = fileObj.createReadStream('images');
var writeStream = fileObj.createWriteStream('s3images');
readStream.pipe(writeStream);
});
}
Hopefully after this you will now see your new store's file sizes matches the old one!
3) Optionally, remove the old store. If you keep both, inserted files are added to both, with priority given to the first store in the array.
Reference: https://github.com/CollectionFS/Meteor-CollectionFS/issues/747
Related
I am trying to build a Meteor package that generates static files for the client to consume. I cannot seem to figure this out. I have tried to write files to the public directory as well as adding assets via compileStep.addAsset, but neither appear to work.
Is there a standard way to do this?
I see a very similar question, but it is a bit old & does not appear to work anymore.
Until you find a better solution consider using collectionFS. You can serve from either filesystem or gridfs as shown below. This way you can avoid worrying about mapping urls to the files because collectionFS does it for you.
Images = new FS.Collection("images", {
stores: [new FS.Store.GridFS("images", {})]
});
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images", {path: "C:/uploads"})]
});
Inserting and linking to is handled with the following.
Images.insert(file, function (err, fileObj) {
});
Images.findOne().url();
Add the following packages depending on your usage.
meteor add cfs:standard-packages
meteor add cfs:gridfs
meteor add cfs:filesystem
I'm developing an ASP.NET webapp that has a multilanguage feature allowing the webmaster to create new languages at runtime.
The approach that I was thinking is the following:
The user selects one available (not created) language.
When the user confirms, the application automatically copies a set of existing resources, replacing the filename with the new culture. For example: default.aspx.en-us.resx to default.aspx.es-ar.resx.
The user edits the recently created resources.
Currently I'm having troubles with step number 2. I've achieved to copy the resources, but then these new resources are ignored. I think that this happens because the new resources are not included in the running assembly, and therefore are being ignored.
When I test the following code in my local project, I would have to manually add the new resources to the solution and then recompile to make it work.
Does anyone know how to make this work?
This is the code of the mentioned copy.
string _dir = path_ + "App_LocalResources\\\\";
DirectoryInfo _dirInfo = new DirectoryInfo(_dir);
foreach (FileInfo _file in _dirInfo.GetFiles("*en-us.resx")) {
_file.CopyTo(_dir + _file.Name.Replace("en-us", idioma_.Cultura));
}
string _dir2 = path_ + "App_GlobalResources\\\\";
_dirInfo = new DirectoryInfo(_dir2);
foreach (FileInfo _file in _dirInfo.GetFiles("*en-us.resx")) {
_file.CopyTo(_dir2 + _file.Name.Replace("en-us", idioma_.Cultura));
}
Thank you very much.
Creating or editing Resource files is not possible the same way as reading data.
In order to create or edit a resource file, you should do it the same way you create or edit XML files because resource files have with a specific structured XML elements.
Maybe this article will help you...
I have 2 different project. One is supposed to upload images (admin) and the other is supposed to show them.
I was writing something like "/Contents/images/image path"... But wait! I will I upload the images from the application into that address?
Any help and suggestions please.
If you have two applications that will interact with the same files, it's probably better to have an ImageController with an action that allows you to upload/download the image rather than storing them directly as content. That way both applications can reference the same file location or images stored in a database and manipulate them. Your download action would simply use a FileContentResult to deliver the bytes from the file. You can derive the content type from the file extension.
Example using a database. Note that I assume that the database table contains the content type as determined at upload time. You could also use a hybrid approach that stores the image metadata in a database and loads the actual file from a file store.
public class ImageController : Controller
{
public ActionResult Get( int id )
{
var context = new MyDataContext();
var image = context.Images.SingleOrDefault( i => i.ID == id );
if (image != null)
{
return File( image.Content, image.ContentType );
}
// or you could return a placeholder image here if appropriate.
throw new HttpException( 404, "The image does not exist" );
}
}
An alternative would be to incorporate your administrative interface in an area of the same application rather than in a separate project. This way you could reuse the content/images directory if you wanted. I find that when you have dynamic images the database or a hybrid approach works better from a programming perspective since it's more consistent with the rest of your data model.
you could try like this..
Let's assume that all of your images are in Project A and you want to use the same images in Project B.
Open Project B with Visual Studio. In the Solution Explorer, right click your Project Name and select "Add Existing Item...".
Browse to the physical location on disc where your images in Project A are stored and select the files that you want to import.
You'll then be able to access those images from project A in Project B.
How does one create an array of loaders?
The bigger picture:
I have written a mapping program in flex. I want to change my mapping program so that all I need to do is drop in a new xml file instead of going into my flex file and adding the exact number of item loaders I need. So I guess I'm looking for an array of loaders that can load the image files that are within my XML file.
xml file example:
<locations>
<location>
<name>Big Star</name>
<street>123 Some St.</street>
<city>City</city>
<state>XX</state>
<zip>555555</zip>
<lat>12.34567</lat>
<long>-67.54321</long>
<iconFile>bigStar_icon.gif</iconFile>
<imageFile>bigStar_img.swf</imageFile>
<motion>no</motion>
<featured>yes</featured>
<category>Grocery</category>
</location>
</locations>
this xml can sometimes have 2000 locations.
Yeah, that's a pretty bad question. Literally (if facetiously):
var loaders:Array = [new Loader(), new Loader()];
Trying to read into what you asked, it sounds like you are trying to load up a whole bunch of stuff and handle them all loading together somehow... and if you have to ask, you're going to struggle.
You could try using the Bulk Loader library though, which does this for you reasonably well. There are probably others.
Not a direct answer to the question since it's a bit vague + #alecmce already gave an answer (I would go for a loader queue such as BulkLoader in this situation as well).
However, since I noticed a similar question some time ago I just wanted to point out that instantiating all the loaders at once just feels a bit wrong.
Wouldn't it be a bit appropriate to just store the urls and handle process them one by one ?
Basic example :
(beware I typed it in without testing...)
// So here's the point: only Strings are stored ...
var urls:Array = new Array('image1.jpg','image2.jpg',image3.jpg);
loadNext();
function loadNext()
{
if(urls.length() == 0)
return;
load(urls.shift())
}
function load(url:String):void
{
// The loader is created lazily just before before we need it
var loader:Loader = new Loader(new URLRequest(url));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded)
loader.load(url);
}
function onLoaded(e:Event):void
{
event.target.removeEventListener(Event.COMPLETE, onLoaded);
addChild(event.target.content); // ... or whatever has to happen here.
loadNext();
}
how can i cycle thru a local folder to add all (or some) files names and references to that file in an array using actionscript 3.0?
var fileArray:Array = new Array();
for (var item:Object in "../myFolder/")
{
trace(item.name);
fileArray.push(item);
}
something like this?
You can only access the file system using AIR :/, or by having Flex make an HTTP call to a server-side language like ruby/python/php and having it return that information.
Here is an AIR Directory Listing Example (you'll have to resize the blog's code blocks because of the formatting).
Hope that helps,
Lance