无法通过Paperclip将存储在S3上的文件添加为ActionMailer中的附件

时间:2013-03-18 04:31:29

标签: ruby-on-rails paperclip actionmailer

我正在使用Paperclip和S3在Rails 3应用程序中上传和存储文件。上传文件效果很好,但是当我尝试使用actionmailer将上传的文件附加到电子邮件时,我遇到了问题。经过大量的故障排除后,希望有人可以提供一些提示。

从高层来看,似乎我可能需要首先下载文件,在附加之前使用某种下载方法,这是建议的,但我并没有完全遵循如何实现 - paperclip + ActionMailer - Adding an attachment? < / p>

在应用程序中,用户上传文件(本例中为测验)后,应通过电子邮件通知管理员用户上传的文件。我一直在遇到“没有这样的文件或目录”。以下是我正在使用的代码。任何想法或建议将不胜感激!

Quiz.rb model - what users are uploading:

class Quiz < ActiveRecord::Base
attr_accessible :quiz_path, :user_id, :tutorial_id

validates_presence_of :quiz_path
validates_attachment_size :quiz_path, :less_than => 50.kilobytes    
validates_attachment_presence :quiz_path 
validates_attachment_content_type :quiz_path, 
  :content_type => ["application/pdf","application/vnd.ms-excel",     
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
  :message => 'We only accept Microsoft Excel files ending in .xlsx or .xls'

belongs_to :user
belongs_to :tutorial
has_attached_file :quiz_path,
:storage => :s3,
:s3_permissions => :private,
:path => "quizzes/:attachment/:style/:id.:extension",
:storage => :s3,
:s3_credentials => {
  :access_key_id => ENV["AWS_ACCESS_KEY_ID"],
  :bucket => ENV["S3_BUCKET_NAME"],
  :secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
}

end

AdminMailer类:

 class AdminMailer < ActionMailer::Base

  default from: "info@mydomain.com"

  def admin_upload_notification_email(quiz, current_user)
  @url  = "http://mydomain.com"
  @quiz = quiz
  @user = current_user
  mail(to: "me@mydomain.com", :subject => "New Upload From #{@user.email}")
  attachments["#{quiz.quiz_path_file_name}"] = File.read("{quiz.quiz_path.expiring_url(60)}")
  end
 end

还添加了QuizzesController:

def create
 @user = current_user
 @quiz = @user.quizzes.create(params[:quiz])

 respond_to do |format|
  if @quiz.save
    UserMailer.upload_notification_email(@user).deliver
    AdminMailer.admin_upload_notification_email(@quiz, @user).deliver

    format.html { redirect_to @user, notice: 'Your skill assessment answer file was successfully uploaded.  We will review your responses and email you a link to your results as soon as possible.' }
    format.json { render json: @user, status: :created, location: @quiz }
  elsif @quiz.errors.any?
    flash[:error] = 'Please make sure you selected your answer file and it ended in ".xlsx".'
    return(redirect_to :back)
  else  
    format.html { redirect_to @user, notice: 'No file was selected.  Please back and choose "Select Your Answer File" before submitting.' }
    format.json { render json: @quiz.errors, status: :unprocessable_entity }
  end
 end
end

2 个答案:

答案 0 :(得分:20)

在弄乱了一些之后,能够让它运转起来。以下是对我有用的 - 希望它可以帮助某人。关键是使用open uri,因为测验文件在S3上。

class AdminMailer < ActionMailer::Base

require 'open-uri'

default from: "sales@mydomain.com"

def admin_upload_notification_email(quiz, current_user)
  @url  = "http://mydomain.com"
  @quiz = quiz
  @user = current_user
  attachments["#{quiz.quiz_path_file_name}"] = open("#{quiz.quiz_path.expiring_url(60)}").read

  mail(to: "admin@mydomain.com", :subject => "New Upload From #{@user.email}")
end


end

答案 1 :(得分:0)

就我而言,问题是在@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); try{ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); } catch (Exception e){ Log.e("Menu", "Full screen not supported under API 19 (4.4 KitKat)"); } mainLinearLayout = (LinearLayout) findViewById(R.id.mainLinearLayout); listView = (ListView) findViewById(R.id.listView); listView.setItemsCanFocus(false); listView.setDivider(null); listView.setFocusable(false); listView.setDividerHeight(0); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Channel channel = channels.get(position); if (position == menuAdapter.getSelectedPosition()) { if ((new Random(System.currentTimeMillis())).nextBoolean()) { openChannel(channel); } else { tempChannel = channel; Log.i("Menu", "Playing ad"); if (interstitialAd.isLoaded()) interstitialAd.show(); } } else { menuAdapter.setSelectedPosition(position, listView); } Picasso.with(mainActivity).load(channel.artUrl).into(new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { BitmapDrawable bmDrawable = new BitmapDrawable(getResources(), bitmap); if (bmDrawable != null) bmDrawable.setAlpha(80); mainLinearLayout.setBackground(bmDrawable); } @Override public void onBitmapFailed(Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }); } }); mainActivity = this; bannerAd = new AdView(this); bannerAd.setAdSize(AdSize.BANNER); bannerAd.setAdUnitId(getAdmobBannerId()); AdRequest adRequest = new AdRequest.Builder().build(); bannerAd.loadAd(adRequest); interstitialAd = new InterstitialAd(this); interstitialAd.setAdUnitId(getAdmobIntersitialId()); interstitialAd.setAdListener(new AdListener() { @Override public void onAdClosed() { openChannel(tempChannel); } }); interstitialAd.loadAd((new AdRequest.Builder()).build()); mainLinearLayout.addView(bannerAd, 0); new WebServiceJob().execute(); } public String getAdmobBannerId() { SharedPreferences preferences = getSharedPreferences("YTApp", MODE_PRIVATE); String result = preferences.getString("admob_banner", null); if (result == null) { String defaultID = "ca-app-pub-"; preferences.edit().putString("admob_banner", defaultID).apply(); return defaultID; } return result; } public String getAdmobIntersitialId() { SharedPreferences preferences = getSharedPreferences("YTApp", MODE_PRIVATE); String result = preferences.getString("admob_intersitial", null); if (result == null) { String defaultID = "ca-app-pub4"; preferences.edit().putString("admob_intersitial", defaultID).apply(); return defaultID; } return result; } public void artDownloaded(){ numArtDownloaded++; if(numArtDownloaded == channels.size()) updateUIWithScroll(); } public void updateUIWithScroll(){ updateUI(); if(!menuAdapter.isScrolling) { menuAdapter.isScrolling = true; listView.post(new Runnable() { @Override public void run() { Log.i("Menu", "Scrolling"); listView.smoothScrollToPosition(menuAdapter.getSelectedPosition()); menuAdapter.isScrolling = false; } }); } } public void updateUI() { try { ArrayList<String> channelNames = new ArrayList<>(); for (Channel channel : channels) channelNames.add(channel.title); menuAdapter = new MenuAdapter(this, R.layout.listitemright, channelNames, getSharedPreferences("YTApp", MODE_PRIVATE).getInt("selectedChannelNr", -1)); listView.setAdapter(menuAdapter); if (menuAdapter.getSelectedPosition() != -1) { Picasso.with(mainActivity).load(channels.get(menuAdapter.getSelectedPosition()).artUrl).into(new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { BitmapDrawable bmDrawable = new BitmapDrawable(getResources(), bitmap); if (bmDrawable != null) bmDrawable.setAlpha(80); mainLinearLayout.setBackground(bmDrawable); } @Override public void onBitmapFailed(Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }); } } catch (Exception e){} } 电话中指定了content_type: "text/html"。删除它修复了我在Rails 4上的问题。

mail()

这样可以在Outlook和Gmail上正确呈现PDF文档附件,但应该可以在任何地方使用。