将文本文件从 Android 上传到 Rails 会导致内容类型欺骗错误

Posted

技术标签:

【中文标题】将文本文件从 Android 上传到 Rails 会导致内容类型欺骗错误【英文标题】:uploading text file from Android to Rails gives Content Type Spoof Error 【发布时间】:2015-10-13 11:48:42 【问题描述】:

我有一个希望将文件发送到我的 Rails 服务器的 android 客户端。我将 Paperclip Gem 用于 Rails,这是我在 WebRick 控制台中遇到的错误:

在 2015-07-23 16:51:20 +0800 为 192.168.63.142 开始 POST "/logs" ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations" LogsController#create 作为 html 处理 参数:"log"=>"description"=>"Description", "user_id"=>"1", "file"=>#, @original_filename="bugreport-1hour-head.txt", @content_type= "application/octet-stream", @headers="Content-Disposition: form-data; name=\"log[file]\"; filename=\"bugreport-1hour-head.txt\"\r\nContent-Type : 应用程序/八位字节流\r\n"> 命令 :: file -b --mime '/tmp/9859aa87e4cbf0f33fd178012d8819b720150723-8057-lwvwns.txt' [回形针] 内容类型欺骗:文件名 bugreport-1hour-head.txt(来自标题的应用程序/八位字节流,[#] 来自扩展名),从文件命令中发现的内容类型:文本/纯文本。请参阅文档以允许这种组合。 (0.1ms) 开始交易 命令 :: file -b --mime '/tmp/9859aa87e4cbf0f33fd178012d8819b720150723-8057-1ndzzr1.txt' [回形针] 内容类型欺骗:文件名 bugreport-1hour-head.txt(来自标题的应用程序/八位字节流,[#] 来自扩展名),从文件命令中发现的内容类型:文本/纯文本。请参阅文档以允许这种组合。 (0.2ms) 回滚事务 渲染日志/_form.html.erb (16.6ms) 在布局/应用程序中渲染日志/new.html.erb (21.6ms) 在 656 毫秒内完成 200 次 OK(查看次数:306.1 毫秒 | ActiveRecord:0.7 毫秒)

上面写着

从文件命令中发现的内容类型:文本/纯文本。请参阅文档以允许这种组合。

但我已经在下面的模型中允许内容类型 text/plain

Android 代码:

 mSendLogs.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            String url = "http://192.168.63.145:3000/logs";
            File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),
                    "bugreport-1hour-head.txt");
            try 
                HttpClient httpclient = new DefaultHttpClient();

                HttpPost httppost = new HttpPost(url);
                MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
                multipartEntity.addPart("log[description]", new StringBody("Description"));
                multipartEntity.addPart("log[user_id]", new StringBody("1"));
                multipartEntity.addPart("log[file]", new FileBody(file) );
                httppost.setEntity(multipartEntity);

                HttpResponse response = httpclient.execute(httppost);
                String statusCode = response.getEntity().getContent().toString();
                Log.d("Benggal", "http.fr.server: " + statusCode + "Upload Logs");

             catch (Exception e) 
                Log.e("Benggal",e.toString());
            
        
    );

带有回形针值的 Rails 模型:

class Log < ActiveRecord::Base
has_attached_file :file
validates_attachment_content_type :file, :content_type => "text/plain"

结束

Rails 控制器的保存操作:

 # POST /logs
  # POST /logs.json
  def create
    @log = Log.new(log_params)

    respond_to do |format|
      if @log.save
        format.html  redirect_to @log, notice: 'Log was successfully created.' 
        format.text @log.file.url
        format.json  render :show, status: :created, location: @log 
      else
        format.html  render :new 
        format.json  render json: @log.errors, status: :unprocessable_entity 
      end
    end
  end

【问题讨论】:

看起来 android 将其发送为 application/octet-stream,而不是 text/plain,并且不匹配会导致异常。 伙计,你是对的!我将文件实体编辑为 multipartEntity.addPart("log[file]", new FileBody(file,"text/plain") );有效!请给出答案,我会接受的。 【参考方案1】:

我认为此消息是由内容欺骗的验证检查引发的。 对于 Paperclip v.4,这会产生一个错误 [https://github.com/thoughtbot/paperclip/issues/1429][1]

虽然对于 Paperclip v.3,它似乎只是抛出了一个弃用警告,[https://github.com/thoughtbot/paperclip/issues/1423][2]

所以要么..在Gemfile中使用它

 gem "paperclip", "~> 3.5.3"

将此添加到初始化程序以禁用欺骗保护:

config/initializers/paperclip_media_type_spoof_detector_override.rb

require 'paperclip/media_type_spoof_detector'
module Paperclip
  class MediaTypeSpoofDetector
    def spoofed?
      false
    end
  end
end

您可以在config/initializers 中指定创建paperclip.rb 文件的mime 类型。

Paperclip.options[:content_type_mappings] = 
  :txt=> 'application/octet-stream'

【讨论】:

【参考方案2】:

您的 Android 客户端以 application/octet-steam 而不是 text/plain 发送文件,这会导致 Paperclip 混淆,从而导致此异常。您可能必须修复客户端才能使其正常工作。

【讨论】:

以上是关于将文本文件从 Android 上传到 Rails 会导致内容类型欺骗错误的主要内容,如果未能解决你的问题,请参考以下文章

将“本地”文件从 nodejs 上传到 rails graphql 后端(服务器到服务器)

从 jquery 将数据发布到 rails 控制器不起作用

使用 ruby​​/rails 将文件上传到网站

如何将 React Native 应用程序上的本地图像文件上传到 Rails api?

使用 ASIHTTPRequest 从 iPhone 上传到 Ruby on Rails

将文件夹参数添加到 Rails 简单表单上传