From 86119486293cb783b6a5b5aca23b4a70abbca24d Mon Sep 17 00:00:00 2001 From: GVerso <112283257+GabrielReverso@users.noreply.github.com> Date: Sat, 26 Nov 2022 12:35:48 -0300 Subject: [PATCH] doc: Translation of README.md into Brazilian Portuguese. (#904) --- README_pt_BR.md | 841 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 841 insertions(+) create mode 100644 README_pt_BR.md diff --git a/README_pt_BR.md b/README_pt_BR.md new file mode 100644 index 00000000..ce5b453a --- /dev/null +++ b/README_pt_BR.md @@ -0,0 +1,841 @@ +

+ npm formidable package logo +

+ +# formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url] + +> A Node.js module for parsing form data, especially file uploads. + +[![Code style][codestyle-img]][codestyle-url] +[![codecoverage][codecov-img]][codecov-url] +[![linux build status][linux-build-img]][build-url] +[![windows build status][windows-build-img]][build-url] +[![macos build status][macos-build-img]][build-url] + +Se você tiver qualquer tipo de pergunta sobre _como_ fazer, por favor leia o [Contributing +Guia][contributing-url] e [Código de Conduta][code_of_conduct-url] +documentos.
Para relatórios de bugs e solicitações de recursos, [crie uma +issue][open-issue-url] ou ping [@tunnckoCore / @3a1FcBx0](https://twitter.com/3a1FcBx0) +no Twitter. + +[![Conventional Commits][ccommits-img]][ccommits-url] +[![Minimum Required Nodejs][nodejs-img]][npmv-url] +[![Tidelift Subscription][tidelift-img]][tidelift-url] +[![Buy me a Kofi][kofi-img]][kofi-url] +[![Renovate App Status][renovateapp-img]][renovateapp-url] +[![Make A Pull Request][prs-welcome-img]][prs-welcome-url] + +Este projeto é [semanticamente versionado](https://semver.org) e está disponível como +parte da [Assinatura Tidelift][tidelift-url] para nível profissional +garantias, suporte aprimorado e segurança. +[Saiba mais.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise) + +_Os mantenedores do `formidable` e milhares de outros pacotes estão trabalhando +com Tidelift para fornecer suporte comercial e manutenção para o Open Source +dependências que você usa para construir seus aplicativos. Economize tempo, reduza riscos e +melhorar a integridade do código, enquanto paga aos mantenedores das dependências exatas que você +usar._ + +[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url] +[![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url] + +## Status do Projeto: Mantido + +_Verifique [VERSION NOTES](https://github.com/node-formidable/formidable/blob/master/VERSION_NOTES.md) para obter mais informações sobre os planos v1, v2 e v3, NPM dist-tags e branches._ + +Este módulo foi inicialmente desenvolvido por +[**@felixge**](https://github.com/felixge) para +[Transloadit](http://transloadit.com/), um serviço focado em upload e +codificação de imagens e vídeos. Foi testado em batalha contra centenas de GBs de +uploads de arquivos de uma grande variedade de clientes e é considerado pronto para produção +e é usado na produção por anos. + +Atualmente, somos poucos mantenedores tentando lidar com isso. :) Mais contribuidores +são sempre bem-vindos! ❤️ Pule +[issue #412](https://github.com/felixge/node-formidable/issues/412) que está +fechado, mas se você estiver interessado, podemos discuti-lo e adicioná-lo após regras estritas, como ativar o Two-Factor Auth em suas contas npm e GitHub. + +## Destaques + +- [Rápido (~ 900-2500 mb/seg)](#benchmarks) e analisador multiparte de streaming +- Gravar uploads de arquivos automaticamente no disco (opcional, consulte + [`options.fileWriteStreamHandler`](#options)) +- [API de plug-ins](#useplugin-plugin) - permitindo analisadores e plug-ins personalizados +- Baixo consumo de memória +- Tratamento de erros gracioso +- Cobertura de teste muito alta + +## Instalar + +Este projeto requer `Node.js >= 10.13`. Instale-o usando +[yarn](https://yarnpkg.com) ou [npm](https://npmjs.com).
_Nós altamente +recomendamos usar o Yarn quando pensar em contribuir para este projeto._ + +Este é um pacote de baixo nível e, se você estiver usando uma estrutura de alto nível, _pode_ já estar incluído. Verifique os exemplos +abaixo e a pasta [examples/](https://github.com/node-formidable/formidable/tree/master/examples). + +``` +# v2 +npm install formidable +npm install formidable@v2 + +# v3 +npm install formidable@v3 +``` + +_**Nota:** Em um futuro próximo, a v3 será publicada na dist-tag `latest` do NPM. +Versões futuras não prontas serão publicadas nas dist-tags `*-next` para a versão correspondente._ + + +## Exemplos + +Para mais exemplos veja o diretório `examples/`. + +### com módulo http Node.js + +Analisar um upload de arquivo de entrada, com o +[Módulo `http` integrado do Node.js](https://nodejs.org/api/http.html). + +```js +import http from 'node:http'; +import formidable, {errors as formidableErrors} from 'formidable'; + +const server = http.createServer((req, res) => { + if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') { + // analisar um upload de arquivo + const form = formidable({}); + + form.parse(req, (err, fields, files) => { + if (err) { + // exemplo para verificar um erro muito específico + if (err.code === formidableErrors.maxFieldsExceeded) { + + } + res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' }); + res.end(String(err)); + return; + } + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ fields, files }, null, 2)); + }); + + return; + } + + // mostrar um formulário de upload de arquivo + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` +

With Node.js "http" module

+
+
Text field title:
+
File:
+ +
+ `); +}); + +server.listen(8080, () => { + console.log('Server listening on http://localhost:8080/ ...'); +}); +``` + +### com Express.js + +Existem várias variantes para fazer isso, mas o Formidable só precisa do Node.js Request +stream, então algo como o exemplo a seguir deve funcionar bem, sem nenhum middleware [Express.js](https://ghub.now.sh/express) de terceiros. + +Ou tente o +[examples/with-express.js](https://github.com/node-formidable/formidable/blob/master/examples/with-express.js) + +```js +import express from 'express'; +import formidable from 'formidable'; + +const app = express(); + +app.get('/', (req, res) => { + res.send(` +

With "express" npm package

+
+
Text field title:
+
File:
+ +
+ `); +}); + +app.post('/api/upload', (req, res, next) => { + const form = formidable({}); + + form.parse(req, (err, fields, files) => { + if (err) { + next(err); + return; + } + res.json({ fields, files }); + }); +}); + +app.listen(3000, () => { + console.log('Server listening on http://localhost:3000 ...'); +}); +``` + +### com Koa e Formidable + +Claro, com [Koa v1, v2 ou future v3](https://ghub.now.sh/koa) as coisas +sao muito parecidas. Você pode usar `formidable` manualmente como mostrado abaixo ou através +do pacote [koa-better-body](https://ghub.now.sh/koa-better-body) que é +usando `formidable` sob o capô e suporte a mais recursos e diferentes +corpos de solicitação, verifique sua documentação para mais informações. + +_Nota: este exemplo está assumindo Koa v2. Esteja ciente de que você deve passar `ctx.req` +que é a solicitação do Node.js e **NÃO** o `ctx.request` que é a solicitação do Koa +objeto - há uma diferença._ + +```js +import Koa from 'Koa'; +import formidable from 'formidable'; + +const app = new Koa(); + +app.on('error', (err) => { + console.error('server error', err); +}); + +app.use(async (ctx, next) => { + if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') { + const form = formidable({}); + + // não muito elegante, mas é por enquanto se você não quiser usar `koa-better-body` + // ou outros middlewares. + await new Promise((resolve, reject) => { + form.parse(ctx.req, (err, fields, files) => { + if (err) { + reject(err); + return; + } + + ctx.set('Content-Type', 'application/json'); + ctx.status = 200; + ctx.state = { fields, files }; + ctx.body = JSON.stringify(ctx.state, null, 2); + resolve(); + }); + }); + await next(); + return; + } + + // mostrar um formulário de upload de arquivo + ctx.set('Content-Type', 'text/html'); + ctx.status = 200; + ctx.body = ` +

With "koa" npm package

+
+
Text field title:
+
File:
+ +
+ `; +}); + +app.use((ctx) => { + console.log('The next middleware is called'); + console.log('Results:', ctx.state); +}); + +app.listen(3000, () => { + console.log('Server listening on http://localhost:3000 ...'); +}); +``` + +## Benchmarks + +O benchmark é bastante antigo, da antiga base de código. Mas talvez seja bem verdade. +Anteriormente, os números giravam em torno de ~ 500 mb/s. Atualmente com a mudança para o novo +Node.js Streams API, é mais rápido. Você pode ver claramente as diferenças entre as +versões do Node. + +_Observação: um benchmarking muito melhor pode e deve ser feito no futuro._ + +Benchmark realizado em 8 GB de RAM, Xeon X3440 (2,53 GHz, 4 núcleos, 8 threads) + +``` +~/github/node-formidable master +❯ nve --parallel 8 10 12 13 node benchmark/bench-multipart-parser.js + + ⬢ Node 8 + +1261.08 mb/sec + + ⬢ Node 10 + +1113.04 mb/sec + + ⬢ Node 12 + +2107.00 mb/sec + + ⬢ Node 13 + +2566.42 mb/sec +``` + +![benchmark 29 de janeiro de 2020](./benchmark/2020-01-29_xeon-x3440.png) + +## API + +### Formidable / IncomingForm + +Todos os mostrados são equivalentes. + +_Por favor, passe [`options`](#options) para a função/construtor, não atribuindo +eles para a instância `form`_ + +```js +import formidable from 'formidable'; +const form = formidable(options); +``` + +### Opções + +Veja seus padrões em [src/Formidable.js DEFAULT_OPTIONS](./src/Formidable.js) +(a constante `DEFAULT_OPTIONS`). + +- `options.encoding` **{string}** - padrão `'utf-8'`; define a codificação para campos de formulário de entrada, +- `options.uploadDir` **{string}** - padrão `os.tmpdir()`; o diretório para colocar os uploads de arquivos. Você pode movê-los mais tarde usando `fs.rename()`. +- `options.keepExtensions` **{boolean}** - padrão `false`; incluir as extensões dos arquivos originais ou não +- `options.allowEmptyFiles` **{boolean}** - padrão `false`; permitir upload de arquivos vazios +- `options.minFileSize` **{number}** - padrão `1` (1byte); o tamanho mínimo do arquivo carregado. +- `options.maxFiles` **{number}** - padrão `Infinity`; + limitar a quantidade de arquivos carregados, defina Infinity para ilimitado +- `options.maxFileSize` **{number}** - padrão `200 * 1024 * 1024` (200mb); + limitar o tamanho de cada arquivo carregado. +- `options.maxTotalFileSize` **{number}** - padrão `options.maxFileSize`; + limitar o tamanho do lote de arquivos carregados. +- `options.maxFields` **{number}** - padrão `1000`; limite o número de campos, defina Infinity para ilimitado +- `options.maxFieldsSize` **{number}** - padrão `20 * 1024 * 1024` (20mb); + limitar a quantidade de memória que todos os campos juntos (exceto arquivos) podem alocar em + bytes. +- `options.hashAlgorithm` **{string | false}** - padrão `false`; incluir checksums calculados + para arquivos recebidos, defina isso para algum algoritmo de hash, consulte + [crypto.createHash](https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm_options) + para algoritmos disponíveis +- `options.fileWriteStreamHandler` **{function}** - padrão `null`, que por padrão grava no sistema de arquivos da máquina host cada arquivo analisado; A função + deve retornar uma instância de um + [fluxo gravável](https://nodejs.org/api/stream.html#stream_class_stream_writable) + que receberá os dados do arquivo carregado. Com esta opção, você pode ter qualquer + comportamento personalizado em relação a onde os dados do arquivo carregado serão transmitidos. + Se você deseja gravar o arquivo carregado em outros tipos de armazenamento em nuvem + (AWS S3, armazenamento de blob do Azure, armazenamento em nuvem do Google) ou armazenamento de arquivo privado, + esta é a opção que você está procurando. Quando esta opção é definida, o comportamento padrão de gravar o arquivo no sistema de arquivos da máquina host é perdido. +- `options.filename` **{function}** - padrão `undefined` Use-o para controlar newFilename. Deve retornar uma string. Será associado a options.uploadDir. + +- `options.filter` **{function}** - função padrão que sempre retorna verdadeiro. + Use-o para filtrar arquivos antes de serem carregados. Deve retornar um booleano. + + +#### `options.filename` **{function}** function (name, ext, part, form) -> string + +onde a parte pode ser decomposta como + +```js +const { originalFilename, mimetype} = part; +``` + +_**Observação:** Se este tamanho de campos combinados, ou tamanho de algum arquivo for excedido, um +O evento `'error'` é disparado._ + +```js +// A quantidade de bytes recebidos para este formulário até agora. +form.bytesReceived; +``` + +```js +// O número esperado de bytes neste formulário. +form.bytesExpected; +``` + +#### `options.filter` **{function}** function ({name, originalFilename, mimetype}) -> boolean + +**Observação:** use uma variável externa para cancelar todos os uploads no primeiro erro + +```js +const options = { + filter: function ({name, originalFilename, mimetype}) { + // manter apenas imagens + return mimetype && mimetype.includes("image"); + } +}; +``` + + +### .parse(request, callback) + +Analisa uma `request` do Node.js recebida contendo dados de formulário. Se `callback` for +fornecido, todos os campos e arquivos são coletados e passados para o retorno de chamada. + +```js +const form = formidable({ uploadDir: __dirname }); + +form.parse(req, (err, fields, files) => { + console.log('fields:', fields); + console.log('files:', files); +}); +``` + +Você pode substituir esse método se estiver interessado em acessar diretamente o +fluxo de várias partes. Fazer isso desativará qualquer processamento de eventos `'field'` / `'file'` +que ocorreria de outra forma, tornando você totalmente responsável por lidar com o processamento. + +Sobre `uploadDir`, dada a seguinte estrutura de diretório +``` +project-name +├── src +│ └── server.js +│ +└── uploads + └── image.jpg +``` + +`__dirname` seria o mesmo diretório que o próprio arquivo de origem (src) + + +```js + `${__dirname}/../uploads` +``` + +para colocar arquivos em uploads. + +Omitir `__dirname` tornaria o caminho relativo ao diretório de trabalho atual. Isso seria o mesmo se server.js fosse iniciado a partir de src, mas não de project-name. + + +`null` usará o padrão que é `os.tmpdir()` + +Nota: Se o diretório não existir, os arquivos carregados são __silenciosamente descartados__. Para ter certeza de que existe: + +```js +import {createNecessaryDirectoriesSync} from "filesac"; + + +const uploadPath = `${__dirname}/../uploads`; +createNecessaryDirectoriesSync(`${uploadPath}/x`); +``` + + +No exemplo abaixo, escutamos alguns eventos e os direcionamos para o ouvinte `data`, para +que você possa fazer o que quiser lá, com base em se é antes do arquivo ser emitido, o valor do +cabeçalho, o nome do cabeçalho, no campo , em arquivo e etc. + +Ou a outra maneira poderia ser apenas substituir o `form.onPart` como é mostrado um pouco +mais tarde. + +```js +form.once('error', console.error); + +form.on('fileBegin', (formname, file) => { + form.emit('data', { name: 'fileBegin', formname, value: file }); +}); + +form.on('file', (formname, file) => { + form.emit('data', { name: 'file', formname, value: file }); +}); + +form.on('field', (fieldName, fieldValue) => { + form.emit('data', { name: 'field', key: fieldName, value: fieldValue }); +}); + +form.once('end', () => { + console.log('Done!'); +}); + +// Se você quiser personalizar o que quiser... +form.on('data', ({ name, key, value, buffer, start, end, formname, ...more }) => { + if (name === 'partBegin') { + } + if (name === 'partData') { + } + if (name === 'headerField') { + } + if (name === 'headerValue') { + } + if (name === 'headerEnd') { + } + if (name === 'headersEnd') { + } + if (name === 'field') { + console.log('field name:', key); + console.log('field value:', value); + } + if (name === 'file') { + console.log('file:', formname, value); + } + if (name === 'fileBegin') { + console.log('fileBegin:', formname, value); + } +}); +``` + +### .use(plugin: Plugin) + +Um método que permite estender a biblioteca Formidable. Por padrão, incluímos +4 plug-ins, que são essencialmente adaptadores para conectar os diferentes analisadores integrados. + +**Os plugins adicionados por este método estão sempre ativados.** + +_Consulte [src/plugins/](./src/plugins/) para uma visão mais detalhada dos plug-ins padrão._ + +O parâmetro `plugin` tem essa assinatura: + +```typescript +function(formidable: Formidable, options: Options): void; +``` + +A arquitetura é simples. O `plugin` é uma função que é passada com a instância Formidable (o `form` nos exemplos README) e as opções. + +**Observação:** o contexto `this` da função do plug-in também é a mesma instância. + +```js +const form = formidable({ keepExtensions: true }); + +form.use((self, options) => { + // self === this === form + console.log('woohoo, custom plugin'); + // faça suas coisas; verifique `src/plugins` para inspiração +}); + +form.parse(req, (error, fields, files) => { + console.log('done!'); +}); +``` +**Importante observar**, é que dentro do plugin `this.options`, `self.options` e +`options` PODEM ou NÃO ser iguais. A melhor prática geral é sempre usar o +`this`, para que você possa testar seu plugin mais tarde de forma independente e mais fácil. + +Se você quiser desabilitar alguns recursos de análise do Formidable, você pode desabilitar +o plugin que corresponde ao analisador. Por exemplo, se você deseja desabilitar a análise de +várias partes (para que o [src/parsers/Multipart.js](./src/parsers/Multipart.js) +que é usado em [src/plugins/multipart.js](./src/plugins/multipart.js)), então +você pode removê-lo do `options.enabledPlugins`, assim + +```js +import formidable, {octetstream, querystring, json} from "formidable"; +const form = formidable({ + hashAlgorithm: 'sha1', + enabledPlugins: [octetstream, querystring, json], +}); +``` + +**Esteja ciente** de que a ordem _PODE_ ser importante também. Os nomes correspondem 1:1 a +arquivos na pasta [src/plugins/](./src/plugins). + +Solicitações pull para novos plug-ins integrados PODEM ser aceitas - por exemplo, analisador de +querystring mais avançado. Adicione seu plugin como um novo arquivo na pasta `src/plugins/` (em letras minúsculas) e +siga como os outros plugins são feitos. + +### form.onPart + +Se você quiser usar Formidable para manipular apenas algumas partes para você, você pode fazer +alguma coisa similar. ou ver +[#387](https://github.com/node-formidable/node-formidable/issues/387) para +inspiração, você pode, por exemplo, validar o tipo mime. + +```js +const form = formidable(); + +form.onPart = (part) => { + part.on('data', (buffer) => { + // faça o que quiser aqui + }); +}; +``` + +Por exemplo, force Formidable a ser usado apenas em "partes" que não sejam de arquivo (ou seja, html +Campos) + +```js +const form = formidable(); + +form.onPart = function (part) { + // deixe formidável lidar apenas com partes não arquivadas + if (part.originalFilename === '' || !part.mimetype) { + // usado internamente, por favor, não substitua! + form._handlePart(part); + } +}; +``` + +### Arquivo + +```ts +export interface File { + // O tamanho do arquivo enviado em bytes. + // Se o arquivo ainda estiver sendo carregado (veja o evento `'fileBegin'`), + // esta propriedade diz quantos bytes do arquivo já foram gravados no disco. + file.size: number; + + // O caminho em que este arquivo está sendo gravado. Você pode modificar isso no evento `'fileBegin'` + // caso você esteja insatisfeito com a forma como o formidable gera um caminho temporário para seus arquivos. + file.filepath: string; + + // O nome que este arquivo tinha de acordo com o cliente de upload. + file.originalFilename: string | null; + + // calculado com base nas opções fornecidas. + file.newFilename: string | null; + + // O tipo mime deste arquivo, de acordo com o cliente de upload. + file.mimetype: string | null; + + // Um objeto Date (ou `null`) contendo a hora em que este arquivo foi gravado pela última vez. + // Principalmente aqui para compatibilidade com o [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/). + file.mtime: Date | null; + + file.hashAlgorithm: false | |'sha1' | 'md5' | 'sha256' + // Se o cálculo `options.hashAlgorithm` foi definido, você pode ler o resumo hexadecimal desta var (no final, será uma string) + file.hash: string | object | null; +} +``` + +#### file.toJSON() + +Este método retorna uma representação JSON do arquivo, permitindo que você `JSON.stringify()` +o arquivo que é útil para registrar e responder a solicitações. + +### Eventos + +#### `'progress'` +Emitido após cada bloco de entrada de dados que foi analisado. Pode ser usado para rolar sua própria barra de progresso. **Aviso** Use isso +apenas para a barra de progresso do lado do servidor. No lado do cliente, é melhor usar `XMLHttpRequest` com `xhr.upload.onprogress =` + +```js +form.on('progress', (bytesReceived, bytesExpected) => {}); +``` + +#### `'field'` + +Emitido sempre que um par campo/valor é recebido. + +```js +form.on('field', (name, value) => {}); +``` + +#### `'fileBegin'` + +Emitido sempre que um novo arquivo é detectado no fluxo de upload. +Use este evento se desejar transmitir o arquivo para outro lugar enquanto armazena o upload no sistema de arquivos. + +```js +form.on('fileBegin', (formName, file) => { + // acessível aqui + // formName o nome no formulário () ou http filename para octetstream + // file.originalFilename http filename ou null se houver um erro de análise + // file.newFilename gerou hexoid ou o que options.filename retornou + // file.filepath nome do caminho padrão de acordo com options.uploadDir e options.filename + // file.filepath = CUSTOM_PATH // para alterar o caminho final +}); +``` + +#### `'file'` + +Emitido sempre que um par campo/arquivo é recebido. `file` é uma instância de +`File`. + +```js +form.on('file', (formname, file) => { + // o mesmo que fileBegin, exceto + // é muito tarde para alterar file.filepath + // file.hash está disponível se options.hash foi usado +}); +``` + +#### `'error'` + +Emitido quando há um erro no processamento do formulário recebido. Uma solicitação que +apresenta um erro é pausada automaticamente, você terá que chamar manualmente +`request.resume()` se você quiser que a requisição continue disparando eventos `'data'`. + +Pode ter `error.httpCode` e `error.code` anexados. + +```js +form.on('error', (err) => {}); +``` + +#### `'aborted'` + +Emitido quando a requisição foi abortada pelo usuário. Agora isso pode ser devido a um +evento 'timeout' ou 'close' no soquete. Após este evento ser emitido, um +O evento `error` seguirá. No futuro, haverá um 'timeout' separado +evento (precisa de uma mudança no núcleo do nó). + +```js +form.on('aborted', () => {}); +``` + +#### `'end'` + +Emitido quando toda a solicitação foi recebida e todos os arquivos contidos foram +liberados para o disco. Este é um ótimo lugar para você enviar sua resposta. + +```js +form.on('end', () => {}); +``` + + +### Helpers + +#### firstValues + +Obtém os primeiros valores dos campos, como pré 3.0.0 sem passar múltiplos em uma +lista de exceções opcionais onde arrays de strings ainda são desejados (`