这又是我。我尝试使用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
答案 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,迁移数据库