Làm thế nào để xử lý một tệp tải lên với Meteor?


76

Cách chuẩn tắc để xử lý tải lên tệp với Meteor là gì?


2
Đó là một câu hỏi mơ hồ ... Bạn đang hỏi cách xử lý nó ở phía máy khách hay máy chủ? Dù bằng cách nào, tôi tưởng tượng (tôi chưa bao giờ sử dụng sao băng) rằng cách xử lý tải lên tệp khá giống với bất kỳ máy chủ nào. Phía khách hàng: gửi yêu cầu ĐĂNG đến một URL với tệp như một phần của nội dung yêu cầu. Phía máy chủ: lắng nghe các yêu cầu ĐĂNG tại URL đó và khi có yêu cầu đến, hãy đọc nội dung yêu cầu và làm bất cứ điều gì bạn muốn với bất kỳ tệp nào trong đó. Đó là về cơ bản làm thế nào tôi đã thực hiện nó với nút / mùa xuân ... Nếu bạn có thể cụ thể hơn về những gì bạn cần giúp đỡ với, có lẽ tôi có thể hữu ích hơn ...
JKing

29
Xin chào JKing, bạn nên xem Meteor, đó là lý do tại sao đó là một câu hỏi thú vị: meteor.com
David

Câu trả lời:


17

Hiện tại dường như không có cách nào để tương tác với máy chủ HTTP hoặc thực hiện bất kỳ điều gì liên quan đến HTTP.

Điều duy nhất bạn có thể làm là nói chuyện với máy chủ qua các phương thức RPC được Meteor.methods hiển thị hoặc nói chuyện với mongoDB trực tiếp qua API mongoDB được hiển thị.


Cảm ơn Raynos. Chắc sẽ thử theo cách của LuHan và bỏ qua việc upload bằng JS upload lên S3 hoặc đại loại như vậy.
David

1
@Raynos Bạn có biết liệu API Mongo được tiếp xúc có hỗ trợ GridFS không? Tôi không thể thấy đề cập đến nó.
Steve Jalim

@stevejalim Tôi không biết, hãy đọc mã nguồn cho tập hợp con của API mongo mà nó hỗ trợ
Raynos

1
@stevejalim tôi nhìn vào nguồn không có bất kỳ GridFS hỗ trợ trong minimongo (gói họ sử dụng)
bobbywilson0

3
Tôi đến bữa tiệc ở đây hơi muộn, nhưng bạn cũng có thể xem vài tập cuối của eventedmind.com, nơi tôi đang xây dựng một trình tải lên tệp cho sao băng. Phiên bản tải lên trực tuyến của gói sẽ được phát hành trong tuần này. Nó được gọi là tập tin sao băng.
cmather

44

Tôi đã sử dụng http://filepicker.io . Họ sẽ tải tệp lên, lưu trữ tệp đó vào S3 của bạn và trả lại cho bạn một URL chứa tệp. Sau đó, tôi chỉ cần đưa url vào một DB.

  1. Quên tập lệnh trình chọn tệp vào thư mục khách hàng của bạn.

    wget https://api.filepicker.io/v0/filepicker.js
    
  2. Chèn thẻ đầu vào trình chọn tệp

    <input type="filepicker" id="attachment">
    
  3. Trong phần khởi động, hãy khởi tạo nó:

    Meteor.startup( function() {
        filepicker.setKey("YOUR FILEPICKER API KEY");
        filepicker.constructWidget(document.getElementById('attachment'));
    });
    
  4. Đính kèm trình xử lý sự kiện

    Templates.template.events({
        'change #attachment': function(evt){
            console.log(evt.files);
        }
    });
    

Yay, filepicker.io! Hoàn toàn có tác dụng như một cái duyên với Heroku.
AbigailW

Nó chỉ miễn phí trong 10 ngày dùng thử :(
aladine

8
Pfff .. Tôi sẽ không trả 100 đô la chiều chỉ để tải tệp lên S3.
Rijk

6
Echo @rijk, không biết tại sao dịch vụ trả phí lại là câu trả lời được bình chọn số 1 .. github.com/VeliovGroup/Meteor-Files hoặc themeteorchef.com/recipes/uploading-files-to-amazon-s3 đều là giải pháp miễn phí triển khai mở nguồn libs.
GFargo

1
Tôi sử dụng edgee:slingshot, nó rất tốt cho các tệp lớn (tải trực tiếp lên S3, không phải qua máy chủ ứng dụng của bạn).
Rijk

26

Đối với hình ảnh, tôi sử dụng một phương pháp tương tự như của Dario ngoại trừ tôi không ghi tệp vào đĩa. Tôi lưu trữ dữ liệu trực tiếp trong cơ sở dữ liệu dưới dạng một trường trên mô hình. Điều này phù hợp với tôi vì tôi chỉ cần hỗ trợ các trình duyệt hỗ trợ API tệp HTML5 . Và tôi chỉ cần hỗ trợ hình ảnh đơn giản.

Template.myForm.events({
  'submit form': function(e, template) {
    e.preventDefault();
    var file = template.find('input type=["file"]').files[0];
    var reader = new FileReader();
    reader.onload = function(e) {
      // Add it to your model
      model.update(id, { $set: { src: e.target.result }});

      // Update an image on the page with the data
      $(template.find('img')).attr('src', e.target.result);
    }
    reader.readAsDataURL(file);
  }
});

19

Tôi vừa nghĩ ra cách triển khai tải lên tệp bằng Meteor.methods và API của tệp HTML5. Cho tôi biết bạn nghĩ gì.


3
Vì vậy, những hướng dẫn đó hoạt động tốt một cách đáng ngạc nhiên. Giải pháp dễ dàng hơn tôi mong đợi gấp 10 lần và mã hoạt động hoàn hảo. Điều đó đang được nói, giải pháp tải các hình ảnh trực tiếp lên hệ thống tệp cục bộ node.js. Lúc đầu, nó hoạt động tốt trên các máy dev cục bộ, nhưng gặp vấn đề với các nhà cung cấp nền tảng như một dịch vụ (PaaS), bao gồm Heroku và Nodjitsu. Vấn đề là có vấn đề về quyền hệ thống tệp với giải pháp này. Vì vậy, giải pháp này yêu cầu lưu trữ máy chủ của riêng bạn hoặc có cơ sở hạ tầng mạnh mẽ hơn, chẳng hạn như Amazon Elasticbeanstalk.
AbigailW 25/12/12

11

Có một gói mới: edgee: slingshot . Nó không tải các tệp lên máy chủ sao băng của bạn, nhưng tốt hơn là theo cách đó vì nó cho phép máy chủ sao băng tập trung vào mục tiêu chính của nó là phục vụ ứng dụng sao băng thay vì xử lý việc truyền tệp tốn kém.

Thay vào đó, nó tải các tập tin lên các dịch vụ lưu trữ đám mây. Hiện tại nó hỗ trợ AWS S3 và Google Cloud Files, nhưng nó cũng sẽ hỗ trợ Rackspace Cloud Files và có lẽ là Cloudinary trong tương lai.

Máy chủ sao băng của bạn chỉ hoạt động như một người điều phối.

Trực tiếp VS Tải lên gián tiếp

Nó cũng là một gói rất linh hoạt và nhẹ.


7

có một gói khí quyển được gọi là bộ định tuyến cho phép điều đó.

trên thực tế, cách tốt nhất để xử lý việc tải lên tệp bây giờ là collectionFS


1
Nhóm bổ trợ CFS không phù hợp để sản xuất - vì chúng liên tục thất bại trong việc triển khai ứng dụng Meteor của chúng tôi, đặc biệt là sau khi nâng cấp ứng dụng lên Meteor 1.0. Tôi thực sự khuyên bạn không nên sử dụng các gói CFS.
Shahriyar Imanov

7

Đây là giải pháp tốt nhất cho thời điểm này. Nó sử dụng collectionFS .

meteor add cfs:standard-packages
meteor add cfs:filesystem

Khách hàng:

Template.yourTemplate.events({
    'change .your-upload-class': function(event, template) {
        FS.Utility.eachFile(event, function(file) {
            var yourFile = new FS.File(file);
            yourFile.creatorId = Meteor.userId(); // add custom data
            YourFileCollection.insert(yourFile, function (err, fileObj) {
                if (!err) {
                   // do callback stuff
                }
            });
        });
    }
});

Người phục vụ:

YourFileCollection = new FS.Collection("yourFileCollection", {
    stores: [new FS.Store.FileSystem("yourFileCollection", {path: "~/meteor_uploads"})]
});
YourFileCollection.allow({
    insert: function (userId, doc) {
        return !!userId;
    },
    update: function (userId, doc) {
        return doc.creatorId == userId
    },
    download: function (userId, doc) {
        return doc.creatorId == userId
    }
});

Bản mẫu:

<template name="yourTemplate">
    <input class="your-upload-class" type="file">
</template>

Tôi sử dụng tất cả mã của bạn. Meteor bắt đầu bình thường nhưng sau khi tôi nhấp vào một mục, nó không tải nó lên máy chủ? Không có gì xảy ra.
Erdem Güngör

@ ErdemGüngör Kiểm tra xem yourTemplateyour-upload-class trong html có giống với Template không. yourTemplate .events và 'change .your-upload-class '. Để thêm console.log tại hàm xử lý sự kiện.
Raz

@Raz Bạn có khuyên dùng chúng không? Nhánh devel của họ (có vẻ là mặc định trên Github) cho biết - "Nhánh này hiện đang được phát triển tích cực (2015-01-26). Nó có lỗi và API có thể tiếp tục thay đổi. Vui lòng giúp kiểm tra và sửa lỗi , nhưng chưa sử dụng trong sản xuất. " Và chi nhánh Master của họ có vẻ khá cũ. Tôi đang nghĩ đến việc mạo hiểm. Bạn có đề nghị gì?
Ayrton Senna

1
@AyrtonSenna Chúng tôi sử dụng nó trong sản xuất cho một dự án nhỏ và nó hoạt động tốt. Nhưng bạn nên thực hiện các bài kiểm tra hồi quy tốt sau mỗi lần kiểm tra meteor update. Không chỉ vì gói này.
Raz

collectionFS hiện không được dùng nữa nên đây không còn là giải pháp nữa. Dù sao, tôi đã thực hiện một giải pháp với nó và phải xử lý nhiều lỗi và cuối cùng khiến tôi thay đổi hoàn toàn sang tùy chọn khác: Uploadcare.
Menda

4

Nếu bạn không yêu cầu các tệp lớn đáng kể hoặc có thể chỉ lưu trữ các tệp trong một khoảng thời gian ngắn thì giải pháp đơn giản này hoạt động rất tốt.

Trong html của bạn ...

<input id="files" type="file" />

Trong bản đồ sự kiện mẫu của bạn ...

Template.template.events({
  'submit': function(event, template){
    event.preventDefault();
    if (window.File && window.FileReader && window.FileList && window.Blob) {
      _.each(template.find('#files').files, function(file) {
        if(file.size > 1){
          var reader = new FileReader();
          reader.onload = function(e) {
            Collection.insert({
              name: file.name,
              type: file.type,
              dataUrl: reader.result
            });
          }
          reader.readAsDataURL(file);
        }
      });
    }
  }
});

Đăng ký Bộ sưu tập và trong một mẫu hiển thị liên kết ...

<a href="{{dataUrl}}" target="_blank">{{name}}</a>

Mặc dù đây có thể không phải là giải pháp mạnh mẽ hoặc thanh lịch nhất cho các tệp lớn hoặc một ứng dụng chuyên sâu về tệp, nó hoạt động rất tốt cho tất cả các loại định dạng tệp nếu bạn muốn thực hiện tải lên và tải xuống / hiển thị tệp đơn giản.



2

Bạn có thể thấy trên lộ trình sao băng rằng tính năng "Mẫu tải tệp lên" được lên lịch cho "Sau 1.0". Vì vậy, chúng ta phải chờ xem một cách chính thức.

Hiện tại, một trong những cách tốt nhất là sử dụng "collectionFS" (là bản xem trước dành cho nhà phát triển 0.3.x tại thời điểm ghi).

Hoặc inkfilepicker (ví dụ: filepicker.io) như được đề xuất ở đây. Nó đủ dễ sử dụng, mặc dù điều này rõ ràng là yêu cầu và kết nối Internet từ phía người dùng.

Nếu nó chỉ để chơi xung quanh, bạn cũng có thể tận dụng tính năng html5. Đại loại vậy .


collectionFS rất mạnh mẽ và hiện tại đây có vẻ là cách tốt nhất để thực hiện.
portetherpodcast,


2

Để thực hiện hành động tương tự như câu trả lời được ủng hộ nhiều nhất mà không phải trả phí filepicker.io, hãy làm theo hướng dẫn cho gói này: https://github.com/Lepozepo/S3

Sau đó, để lấy liên kết, hãy sử dụng mã tương tự như bên dưới. Cuối cùng, cắm url được trả về bởi secureLink vào DB.

Template.YourTemplate.events({
  "click button.upload": function() {
    var files = $("input.file_bag")[0].files;
    S3.upload(files, "/subfolder", function(e,r) {
      console.log(r);
      Session.set('secureLink', r.secure_url);
    })
  }
});
Template.YourTemplate.helpers({
  "files": function() {
    return S3.collection.find();
  },

  "secureLink": function() {
    return Session.get('secureLink');
  }
});

Cảm ơn vì $("input.file_bag")[0].files. Tôi đang loay hoay tìm cách lấy dữ liệu trả về từ đầu vào loại tệp.
Adriano P
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.