使用没有名称的carrierwave上传文件

时间:2016-11-30 13:07:52

标签: ruby-on-rails ruby carrierwave

这又是我。我尝试使用carrierwave上传一些yaml文件。到目前为止一切正常。

因此,正如您所知,对于carrierwave,表格如下所示:

<%= form_for @resume, html: { multipart: true } do |f| %>
      <%= f.label :name %><br>
      <%= f.text_field :name, :required => true %>
      <%= f.label :attachment %><br>
      <%= f.file_field :attachment, :required => true %>
      <br><br>
      <%= f.submit "Save", class: "btn btn-primary" %>
  <% end %>

我现在要做的是删除“名称”字段。我不需要它。所以我认为它非常简单,只需删除表单中的“名称”部分即可。但是上传时出现了错误:

Name can't be blank

所以我现在几乎尝试了一切......我设置了required => false相同的结果。 我去了Github并看了他们的操作方法......有方法可以覆盖这个名字,但没有人关心上传一个没有名字的文件。有人可以告诉我如何在没有此名称字段的情况下上传文件吗?

谢谢!

编辑:

我的简历.rb模型:

class Resume < ActiveRecord::Base
  mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.


end

我的AttachmentUploader:

class AttachmentUploader < CarrierWave::Uploader::Base
  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(yml)
  end

  def filename
    "something.jpg" if original_filename # This is the part where i'm trying around right now.
  end

end

1 个答案:

答案 0 :(得分:1)

尝试删除表name上的列resumes以及其他相关的列strong params, 可能在视图,控制器(<?php namespace League\Flysystem\AwsS3v2; use Aws\Common\Exception\MultipartUploadException; use Aws\S3\Enum\Group; use Aws\S3\Enum\Permission; use Aws\S3\Enum\StorageClass; use Aws\S3\Model\MultipartUpload\AbstractTransfer; use Aws\S3\Model\MultipartUpload\UploadBuilder; use Aws\S3\S3Client; use Guzzle\Service\Resource\Model; use League\Flysystem\Adapter\AbstractAdapter; use League\Flysystem\AdapterInterface; use League\Flysystem\Config; use League\Flysystem\Util; class AwsS3Adapter extends AbstractAdapter { /** * @var array */ protected static $resultMap = [ 'Body' => 'raw_contents', 'ContentLength' => 'size', 'ContentType' => 'mimetype', 'Size' => 'size', 'StorageClass' => 'storage_class', ]; /** * @var array */ protected static $metaOptions = [ 'CacheControl', 'Expires', 'StorageClass', 'ServerSideEncryption', 'Metadata', 'ACL', 'ContentType', 'ContentDisposition', 'ContentLanguage', 'ContentEncoding', ]; /** * @var string bucket name */ protected $bucket; /** * @var S3Client S3 Client */ protected $client; /** * @var array default options[ * Multipart=1024 Mb - After what size should multipart be used * MinPartSize=32 Mb - Minimum size of parts for each part * Concurrency=3 - If multipart is used, how many concurrent connections should be used * ] */ protected $options = [ 'Multipart' => 1024, 'MinPartSize' => 32, 'Concurrency' => 3, ]; /** * @var UploadBuilder Used to upload object using a multipart transfer */ protected $uploadBuilder; /** * Constructor. * * @param S3Client $client * @param string $bucket * @param string $prefix * @param array $options * @param UploadBuilder $uploadBuilder */ public function __construct( S3Client $client, $bucket, $prefix = null, array $options = [], UploadBuilder $uploadBuilder = null ) { $this->client = $client; $this->bucket = $bucket; $this->setPathPrefix($prefix); $this->options = array_merge($this->options, $options); $this->setUploadBuilder($uploadBuilder); } /** * Get the S3Client bucket. * * @return string */ public function getBucket() { return $this->bucket; } /** * Get the S3Client instance. * * @return S3Client */ public function getClient() { return $this->client; } /** * {@inheritdoc} */ public function has($path) { $location = $this->applyPathPrefix($path); return $this->client->doesObjectExist($this->bucket, $location); } /** * {@inheritdoc} */ public function write($path, $contents, Config $config) { $options = $this->getOptions( $path, [ 'Body' => $contents, 'ContentType' => Util::guessMimeType($path, $contents), 'ContentLength' => Util::contentSize($contents), ], $config ); return $this->writeObject($options); } /** * {@inheritdoc} */ public function writeStream($path, $resource, Config $config) { $options = ['Body' => $resource]; $options['ContentLength'] = Util::getStreamSize($resource); $options = $this->getOptions($path, $options, $config); return $this->writeObject($options); } /** * Write an object to S3. * * @param array $options * * @return array file metadata */ protected function writeObject(array $options) { $multipartLimit = $this->mbToBytes($options['Multipart']); // If we don't know the stream size, we have to assume we need to upload using multipart, otherwise it might fail. if ($options['ContentLength'] > $multipartLimit) { $result = $this->putObjectMultipart($options); } else { $result = $this->client->putObject($options); } if ($result === false) { return false; } if (! is_string($options['Body'])) { unset($options['Body']); } return $this->normalizeResponse($options); } /** * {@inheritdoc} */ public function update($path, $contents, Config $config) { if (! $config->has('visibility') && ! $config->has('ACL')) { $config->set('ACL', $this->getObjectACL($path)); } return $this->write($path, $contents, $config); } /** * {@inheritdoc} */ public function updateStream($path, $resource, Config $config) { if (! $config->has('visibility') && ! $config->has('ACL')) { $config->set('ACL', $this->getObjectACL($path)); } return $this->writeStream($path, $resource, $config); } /** * {@inheritdoc} */ public function read($path) { $result = $this->readObject($path); $result['contents'] = (string) $result['raw_contents']; unset($result['raw_contents']); return $result; } /** * {@inheritdoc} */ public function readStream($path) { $result = $this->readObject($path); $result['stream'] = $result['raw_contents']->getStream(); rewind($result['stream']); // Ensure the EntityBody object destruction doesn't close the stream $result['raw_contents']->detachStream(); unset($result['raw_contents']); return $result; } /** * Read an object from the S3Client. * * @param string $path * * @return array */ protected function readObject($path) { $options = $this->getOptions($path); $result = $this->client->getObject($options); return $this->normalizeResponse($result->getAll(), $path); } /** * {@inheritdoc} */ public function rename($path, $newpath) { $this->copy($path, $newpath); $this->delete($path); return true; } /** * {@inheritdoc} */ public function copy($path, $newpath) { $options = $this->getOptions($newpath, [ 'Bucket' => $this->bucket, 'CopySource' => urlencode($this->bucket.'/'.$this->applyPathPrefix($path)), 'ACL' => $this->getObjectACL($path), 'StorageClass' => $this->getStorageClass($path), ]); $this->client->copyObject($options); return true; } /** * {@inheritdoc} */ public function delete($path) { $options = $this->getOptions($path); $this->client->deleteObject($options); return ! $this->has($path); } /** * {@inheritdoc} */ public function deleteDir($path) { $prefix = rtrim($this->applyPathPrefix($path), '/').'/'; return (bool) $this->client->deleteMatchingObjects($this->bucket, $prefix); } /** * {@inheritdoc} */ public function createDir($path, Config $config) { $result = $this->write(rtrim($path, '/').'/', '', $config); if (! $result) { return false; } return ['path' => $path, 'type' => 'dir']; } /** * {@inheritdoc} */ public function getMetadata($path) { $options = $this->getOptions($path); $result = $this->client->headObject($options); return $this->normalizeResponse($result->getAll(), $path); } /** * {@inheritdoc} */ public function getMimetype($path) { return $this->getMetadata($path); } /** * {@inheritdoc} */ public function getSize($path) { return $this->getMetadata($path); } /** * {@inheritdoc} */ public function getTimestamp($path) { return $this->getMetadata($path); } /** * {@inheritdoc} */ public function getVisibility($path) { $options = $this->getOptions($path); $result = $this->client->getObjectAcl($options)->getAll(); $visibility = AdapterInterface::VISIBILITY_PRIVATE; foreach ($result['Grants'] as $grant) { if (isset($grant['Grantee']['URI']) && $grant['Grantee']['URI'] === Group::ALL_USERS && $grant['Permission'] === Permission::READ) { $visibility = AdapterInterface::VISIBILITY_PUBLIC; break; } } return compact('visibility'); } /** * The the ACL visibility. * * @param string $path * * @return string */ protected function getObjectACL($path) { $metadata = $this->getVisibility($path); return $metadata['visibility'] === AdapterInterface::VISIBILITY_PUBLIC ? 'public-read' : 'private'; } /** * Return an object's storage class. * * @param $path * @return string */ public function getStorageClass($path) { $metadata = $this->getMetadata($path); return !empty($metadata['storage_class']) ? $metadata['storage_class'] : StorageClass::STANDARD; } /** * {@inheritdoc} */ public function setVisibility($path, $visibility) { $options = $this->getOptions($path, [ 'ACL' => $visibility === AdapterInterface::VISIBILITY_PUBLIC ? 'public-read' : 'private', ]); $this->client->putObjectAcl($options); return compact('visibility'); } /** * {@inheritdoc} */ public function listContents($dirname = '', $recursive = false) { $dirname = rtrim($dirname, '/') . '/'; $commandOptions = [ 'Bucket' => $this->bucket, 'Prefix' => $this->applyPathPrefix($dirname) ]; $iteratorOptions = []; if (!$recursive) { $commandOptions['Delimiter'] = '/'; $iteratorOptions['return_prefixes'] = true; } $objectsIterator = $this->client->getIterator('listObjects', $commandOptions, $iteratorOptions); $contents = iterator_to_array($objectsIterator); $result = array_map([$this, 'normalizeResponse'], $contents); $result = array_filter($result, function ($value) { return $value['path'] !== false; }); return Util::emulateDirectories($result); } /** * Normalize a result from AWS. * * @param array $object * @param string $path * * @return array file metadata */ protected function normalizeResponse(array $object, $path = null) { $result = ['path' => $path ?: $this->removePathPrefix(isset($object['Key']) ? $object['Key'] : $object['Prefix'])]; $result['dirname'] = Util::dirname($result['path']); if (isset($object['LastModified'])) { $result['timestamp'] = strtotime($object['LastModified']); } if (substr($result['path'], -1) === '/') { $result['type'] = 'dir'; $result['path'] = rtrim($result['path'], '/'); return $result; } $result = array_merge($result, Util::map($object, static::$resultMap), ['type' => 'file']); return $result; } /** * Get options for a AWS call. * * @param string $path * @param array $options * @param Config $config * * @return array AWS options */ protected function getOptions($path, array $options = [], Config $config = null) { $options = array_merge($this->options, $options); $options['Key'] = $this->applyPathPrefix($path); $options['Bucket'] = $this->bucket; if ($config) { $options = array_merge($options, $this->getOptionsFromConfig($config)); } return $options; } /** * Retrieve options from a Config instance. * * @param Config $config * * @return array */ protected function getOptionsFromConfig(Config $config) { $options = []; foreach (static::$metaOptions as $option) { if (! $config->has($option)) { continue; } $options[$option] = $config->get($option); } if ($visibility = $config->get('visibility')) { // For local reference $options['visibility'] = $visibility; // For external reference $options['ACL'] = $visibility === AdapterInterface::VISIBILITY_PUBLIC ? 'public-read' : 'private'; } if ($mimetype = $config->get('mimetype')) { // For local reference $options['mimetype'] = $mimetype; // For external reference $options['ContentType'] = $mimetype; } return $options; } /** * Sends an object to a bucket using a multipart transfer, possibly also using concurrency. * * @param array $options Can have: [Body, Bucket, Key, MinPartSize, Concurrency, ContentType, ACL, Metadata] * * @return bool */ protected function putObjectMultipart(array $options) { // Prepare the upload parameters. /** @var UploadBuilder $uploadBuilder */ $uploadBuilder = $this->getUploadBuilder(); $uploadBuilder->setBucket($options['Bucket']) // This options are always set in the $options array, so we don't need to check for them ->setKey($options['Key']) ->setMinPartSize($options['MinPartSize']) ->setConcurrency($options['Concurrency']) ->setSource($options['Body']) // these 2 methods must be the last to be called because they return ->setClient($this->client); // AbstractUploadBuilder, which makes IDE and CI complain. foreach (static::$metaOptions as $option) { if (! array_key_exists($option, $options)) { continue; } $uploadBuilder->setOption($option, $options[$option]); } $uploader = $uploadBuilder->build(); return $this->upload($uploader); } /** * Perform the upload. Abort the upload if something goes wrong. * * @param AbstractTransfer $uploader * * @return bool */ protected function upload(AbstractTransfer $uploader) { try { $uploader->upload(); } catch (MultipartUploadException $e) { $uploader->abort(); return false; } return true; } /** * Convert megabytes to bytes. * * @param int $megabytes * * @return int */ protected function mbToBytes($megabytes) { return $megabytes * 1024 * 1024; } /** * Set the S3 UploadBuilder. * * @param UploadBuilder $uploadBuilder * * @return $this */ public function setUploadBuilder(UploadBuilder $uploadBuilder = null) { $this->uploadBuilder = $uploadBuilder; return $this; } /** * Get the S3 UploadBuilder. * * @return UploadBuilder */ public function getUploadBuilder() { if (! $this->uploadBuilder) { $this->uploadBuilder = UploadBuilder::newInstance(); } return $this->uploadBuilder; } } ),迁移文件......

然后重新运行drop,迁移数据库