React-Admin <ImageInput> 将图像上传到 rails api

Posted

技术标签:

【中文标题】React-Admin <ImageInput> 将图像上传到 rails api【英文标题】:React-Admin <ImageInput> to upload images to rails api 【发布时间】:2019-06-09 16:05:42 【问题描述】:

我正在尝试使用活动存储将图像从 react-admin 上传到 rails api 后端。

在 react-admin 的文档中它说:“请注意,图像上传返回一个 File 对象。您有责任根据您的 API 行为来处理它。例如,您可以将其编码为 base64,或将其发送为多部分表单数据”我正在尝试将其作为多部分表单发送。

我一直在这里和那里阅读,但我找不到我想要的,至少是我应该如何进行的路线图。

【问题讨论】:

能否展示一下您目前拥有的代码,以便我们为您提供帮助? 【参考方案1】:

您实际上可以在文档的dataProvider section 中找到一个示例。

您必须装饰您的 dataProvider 以启用数据上传。这是在发布资源之前将图像转换为 base64 字符串的示例:

// in addUploadFeature.js
/**
 * Convert a `File` object returned by the upload input into a base 64 string.
 * That's not the most optimized way to store images in production, but it's
 * enough to illustrate the idea of data provider decoration.
 */
const convertFileToBase64 = file => new Promise((resolve, reject) => 
    const reader = new FileReader();
    reader.readAsDataURL(file.rawFile);

    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
);

/**
 * For posts update only, convert uploaded image in base 64 and attach it to
 * the `picture` sent property, with `src` and `title` attributes.
 */
const addUploadFeature = requestHandler => (type, resource, params) => 
    if (type === 'UPDATE' && resource === 'posts') 
        // notice that following condition can be true only when `<ImageInput source="pictures" />` component has parameter `multiple=true`
        // if parameter `multiple` is false, then data.pictures is not an array, but single object
        if (params.data.pictures && params.data.pictures.length) 
            // only freshly dropped pictures are instance of File
            const formerPictures = params.data.pictures.filter(p => !(p.rawFile instanceof File));
            const newPictures = params.data.pictures.filter(p => p.rawFile instanceof File);

            return Promise.all(newPictures.map(convertFileToBase64))
                .then(base64Pictures => base64Pictures.map((picture64, index) => (
                    src: picture64,
                    title: `$newPictures[index].title`,
                )))
                .then(transformedNewPictures => requestHandler(type, resource, 
                    ...params,
                    data: 
                        ...params.data,
                        pictures: [...transformedNewPictures, ...formerPictures],
                    ,
                ));
        
    
    // for other request types and resources, fall back to the default request handler
    return requestHandler(type, resource, params);
;

export default addUploadFeature;

然后您可以将其应用于您的 dataProvider:

// in dataProvider.js
import simpleRestProvider from 'ra-data-simple-rest';
import addUploadFeature from './addUploadFeature';

const dataProvider = simpleRestProvider('http://path.to.my.api/');
const uploadCapableDataProvider = addUploadFeature(dataProvider);

export default uploadCapableDataProvider;

最后,您可以像往常一样在管理员中使用它:

// in App.js
import  Admin, Resource  from 'react-admin';

import dataProvider from './dataProvider';
import PostList from './posts/PostList';

const App = () => (
    <Admin dataProvider=uploadCapableDataProvider>
        <Resource name="posts" list=PostList />
    </Admin>
);

【讨论】:

感谢您的回复。我看过这个例子,但我想要的是将图像作为多部分元素发送 @Tiamon 你做到了吗。我想一次性上传一个带有图片的帖子。【参考方案2】:

使用文件时,在 react 前端使用多部分表单,例如在 API 后端使用 multer。

在 react-admin 中,您应该创建一个 custom dataProvider 并扩展默认值或构建自定义的。根据实现,您应该处理文件/文件上传。在 react-admin 中从您的自定义数据提供者上传一个或多个文件:

// dataProvider.js
// this is only the implementation for a create

case "CREATE":
  const formData = new FormData();

  for ( const param in params.data ) 

    // 1 file
    if (param === 'file') 
      formData.append('file', params.data[param].rawFile);
      continue
    

    // when using multiple files
    if (param === 'files') 
      params.data[param].forEach(file => 
        formData.append('files', file.rawFile);
      );
      continue
    

    formData.append(param, params.data[param]);
  

  return httpClient(`myendpoint.com/upload`, 
    method: "POST",
    body: formData,
  ).then(( json ) => ( data: json );

从那里您可以使用 multer 在您的 API 中获取它,它支持开箱即用的多部分表单。当使用nestjs 时,可能看起来像:

import 
  Controller,
  Post,
  Header,
  UseInterceptors,
  UploadedFile,
 from "@nestjs/common";
import  FileInterceptor  from '@nestjs/platform-express'

@Controller("upload")
export class UploadController 

  @Post()
  @Header("Content-Type", "application/json")
  // multer extracts file from the request body 
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(
    @UploadedFile() file : Record<any, any>
  ) 
    console.log( file )
  

【讨论】:

graphql 解析器应该如何处理这个错误@hajnalbendeguz .any idea 一个很好的描述在:***.com/a/63570461/11067065

以上是关于React-Admin <ImageInput> 将图像上传到 rails api的主要内容,如果未能解决你的问题,请参考以下文章

react-admin 没有'访问控制允许来源'

HTTP 响应中缺少 react-admin

React-Admin 在 SelectInput 中将值更改为自定义值

仪表板上的 React-admin 组件?

React-admin - 如果未经身份验证,我如何强制 Dasbhoard 要求登录

无法在 react-admin 中自定义用户菜单