Carregar arquivos (C#)
por Scott Mitchell
Saiba como permitir que os usuários carreguem arquivos binários (como documentos do Word ou PDF) para o seu site, onde podem ser armazenados no sistema de arquivos do servidor ou no banco de dados.
Introdução
Todos os tutoriais que examinamos até agora funcionaram exclusivamente com dados de texto. No entanto, muitos aplicativos têm modelos de dados que capturam texto e dados binários. Um site de namoro online pode permitir que os usuários carreguem uma foto para associar ao seu perfil. Um site de recrutamento pode permitir que os usuários carreguem seu currículo como um documento do Microsoft Word ou PDF.
Trabalhar com dados binários adiciona um novo conjunto de desafios. Devemos decidir como os dados binários são armazenados no aplicativo. A interface usada para inserir novos registros deve ser atualizada para permitir que o usuário carregue um arquivo de seu computador e etapas extras devem ser executadas para exibir ou fornecer um meio de baixar os dados binários associados a um registro. Neste tutorial e nos próximos três, exploraremos como superar esses desafios. No final desses tutoriais, teremos construído um aplicativo totalmente funcional que associa uma imagem e um folheto em PDF a cada categoria. Neste tutorial específico, examinaremos diferentes técnicas para armazenar dados binários e exploraremos como permitir que os usuários carreguem um arquivo de seu computador e o salvem no sistema de arquivos do servidor Web.
Observação
Os dados binários que fazem parte do modelo de dados de um aplicativo às vezes são chamados de BLOB, um acrônimo para Binary Large OBject. Nestes tutoriais optei por usar a terminologia dados binários, embora o termo BLOB seja sinônimo.
Etapa 1: Criando o trabalho com páginas da Web de dados binários
Antes de começarmos a explorar os desafios associados à adição de suporte para dados binários, vamos primeiro reservar um momento para criar as páginas ASP.NET em nosso projeto de site que precisaremos para este tutorial e os próximos três. Comece adicionando uma nova pasta chamada BinaryData
. Em seguida, adicione as seguintes páginas ASP.NET a essa pasta, certificando-se de associar cada página à Site.master
página mestra:
Default.aspx
FileUpload.aspx
DisplayOrDownloadData.aspx
UploadInDetailsView.aspx
UpdatingAndDeleting.aspx
Figura 1: Adicionar as páginas ASP.NET para os tutoriais relacionados a dados binários
Como nas outras pastas, Default.aspx
na BinaryData
pasta listará os tutoriais em sua seção. Lembre-se de que o SectionLevelTutorialListing.ascx
Controle de Usuário fornece essa funcionalidade. Portanto, adicione esse Controle de Usuário arrastando-o Default.aspx
do Gerenciador de Soluções para o modo de exibição Design da página.
Figura 2: Adicionar o controle de usuário a Default.aspx
(clique para exibir a SectionLevelTutorialListing.ascx
imagem em tamanho real)
Por fim, adicione essas páginas como entradas ao Web.sitemap
arquivo. Especificamente, adicione a seguinte marcação após o Aprimorando o GridView <siteMapNode>
:
<siteMapNode
title="Working with Binary Data"
url="~/BinaryData/Default.aspx"
description="Extend the data model to include collecting binary data.">
<siteMapNode
title="Uploading Files"
url="~/BinaryData/FileUpload.aspx"
description="Examine the different ways to store binary data on the
web server and see how to accept uploaded files from users
with the FileUpload control." />
<siteMapNode
title="Display or Download Binary Data"
url="~/BinaryData/DisplayOrDownloadData.aspx"
description="Let users view or download the captured binary data." />
<siteMapNode
title="Adding New Binary Data"
url="~/BinaryData/UploadInDetailsView.aspx"
description="Learn how to augment the inserting interface to
include a FileUpload control." />
<siteMapNode
title="Updating and Deleting Existing Binary Data"
url="~/BinaryData/UpdatingAndDeleting.aspx"
description="Learn how to update and delete existing binary data." />
</siteMapNode>
Após a atualização Web.sitemap
, reserve um momento para visualizar o site de tutoriais por meio de um navegador. O menu à esquerda agora inclui itens para os tutoriais Trabalhando com dados binários.
Figura 3: O mapa do site agora inclui entradas para os tutoriais Trabalhando com dados binários
Etapa 2: Decidindo onde armazenar os dados binários
Os dados binários associados ao modelo de dados do aplicativo podem ser armazenados em um dos dois locais: no sistema de arquivos do servidor Web com uma referência ao arquivo armazenado no banco de dados; ou diretamente no próprio banco de dados (consulte a Figura 4). Cada abordagem tem seu próprio conjunto de prós e contras e merece uma discussão mais detalhada.
Figura 4: Os dados binários podem ser armazenados no sistema de arquivos ou diretamente no banco de dados (clique para exibir a imagem em tamanho real)
Imagine que quiséssemos estender o banco de dados Northwind para associar uma imagem a cada produto. Uma opção seria armazenar esses arquivos de imagem no sistema de arquivos do servidor Web e registrar o Products
caminho na tabela. Com essa abordagem, adicionaríamos uma ImagePath
coluna à Products
tabela do tipo varchar(200)
, talvez. Quando um usuário carrega uma imagem para Chai, essa imagem pode ser armazenada no sistema de arquivos do servidor Web em ~/Images/Tea.jpg
, onde ~
representa o caminho físico do aplicativo. Ou seja, se o site estiver enraizado no caminho C:\Websites\Northwind\
físico , ~/Images/Tea.jpg
seria equivalente a C:\Websites\Northwind\Images\Tea.jpg
. Depois de fazer o upload do arquivo de imagem, atualizamos o registro Chai na Products
tabela para que sua ImagePath
coluna faça referência ao caminho da nova imagem. Poderíamos usar ~/Images/Tea.jpg
ou apenas Tea.jpg
se decidíssemos que todas as imagens do produto seriam colocadas na pasta do Images
aplicativo.
As principais vantagens de armazenar os dados binários no sistema de arquivos são:
- Facilidade de implementação Como veremos em breve, armazenar e recuperar dados binários armazenados diretamente no banco de dados envolve um pouco mais de código do que ao trabalhar com dados por meio do sistema de arquivos. Além disso, para que um usuário visualize ou baixe dados binários, ele deve receber uma URL para esses dados. Se os dados residirem no sistema de arquivos do servidor Web, a URL será direta. Se os dados estiverem armazenados no banco de dados, no entanto, será necessário criar uma página da Web que recupere e retorne os dados do banco de dados.
- Acesso mais amplo aos dados binários Os dados binários podem precisar estar acessíveis a outros serviços ou aplicativos, aqueles que não podem extrair os dados do banco de dados. Por exemplo, as imagens associadas a cada produto também podem precisar estar disponíveis para os usuários por meio de FTP, caso em que queremos armazenar os dados binários no sistema de arquivos.
- Desempenho se os dados binários forem armazenados no sistema de arquivos, a demanda e o congestionamento de rede entre o servidor de banco de dados e o servidor Web serão menores do que se os dados binários forem armazenados diretamente no banco de dados.
A principal desvantagem de armazenar dados binários no sistema de arquivos é que ele desacopla os dados do banco de dados. Se um registro for excluído da Products
tabela, o arquivo associado no sistema de arquivos do servidor Web não será excluído automaticamente. Devemos escrever código extra para excluir o arquivo ou o sistema de arquivos ficará cheio de arquivos órfãos e não utilizados. Além disso, ao fazer backup do banco de dados, devemos nos certificar de fazer backups dos dados binários associados no sistema de arquivos também. Mover o banco de dados para outro site ou servidor apresenta desafios semelhantes.
Como alternativa, os dados binários podem ser armazenados diretamente em um banco de dados do Microsoft SQL Server 2005 criando uma coluna do tipo varbinary
. Assim como acontece com outros tipos de dados de comprimento variável, você pode especificar um comprimento máximo dos dados binários que podem ser mantidos nessa coluna. Por exemplo, para reservar no máximo 5.000 bytes, use varbinary(5000)
; varbinary(MAX)
permite o tamanho máximo de armazenamento, cerca de 2 GB.
A principal vantagem de armazenar dados binários diretamente no banco de dados é o forte acoplamento entre os dados binários e o registro do banco de dados. Isso simplifica muito as tarefas de administração do banco de dados, como backups ou mover o banco de dados para um site ou servidor diferente. Além disso, a exclusão de um registro exclui automaticamente os dados binários correspondentes. Há também benefícios mais sutis de armazenar os dados binários no banco de dados. Consulte Armazenando arquivos binários diretamente no banco de dados usando o ASP.NET 2.0 para uma discussão mais aprofundada.
Observação
No Microsoft SQL Server 2000 e versões anteriores, o varbinary
tipo de dados tinha um limite máximo de 8.000 bytes. Para armazenar até 2 GB de dados binários, o image
tipo de dados precisa ser usado. Com a adição de no SQL Server 2005, no entanto, o image
tipo de MAX
dados foi preterido. Ele ainda tem suporte para compatibilidade com versões anteriores, mas a Microsoft anunciou que o image
tipo de dados será removido em uma versão futura do SQL Server.
Se você estiver trabalhando com um modelo de dados mais antigo, poderá ver o image
tipo de dados. A tabela do banco de dados Northwind tem uma Picture
coluna que pode ser usada para armazenar os dados binários Categories
de um arquivo de imagem para a categoria. Como o banco de dados Northwind tem suas raízes no Microsoft Access e em versões anteriores do SQL Server, essa coluna é do tipo image
.
Para este tutorial e os próximos três, usaremos as duas abordagens. A Categories
tabela já possui uma Picture
coluna para armazenar o conteúdo binário de uma imagem para a categoria. Adicionaremos uma coluna adicional, BrochurePath
, para armazenar um caminho para um PDF no sistema de arquivos do servidor Web que pode ser usado para fornecer uma visão geral polida e com qualidade de impressão da categoria.
Etapa 3: Adicionando aBrochurePath
coluna àCategories
tabela
Atualmente, a tabela Categorias tem apenas quatro colunas: CategoryID
, CategoryName
, Description
, e Picture
. Além desses campos, precisamos adicionar um novo que aponte para o folheto da categoria (se houver). Para adicionar essa coluna, vá para o Gerenciador de Servidores, faça uma busca detalhada nas Tabelas, clique com o botão direito do mouse na tabela e escolha Abrir Definição de Tabela (consulte a Categories
Figura 5). Se você não vir o Gerenciador de Servidores, abra-o selecionando a opção Gerenciador de Servidores no menu Exibir ou pressione Ctrl+Alt+S.
Adicione uma nova varchar(200)
coluna à Categories
tabela que é chamada BrochurePath
e permite NULL
s e clique no ícone Salvar (ou pressione Ctrl+S).
Figura 5: Adicionar uma BrochurePath
coluna à tabela (clique para exibir a Categories
imagem em tamanho real)
Etapa 4: Atualizando a arquitetura para usar asPicture
colunas eBrochurePath
A CategoriesDataTable
na Camada de Acesso a Dados (DAL) atualmente tem quatro DataColumn
s definidos: CategoryID
, CategoryName
, Description
e NumberOfProducts
. Quando projetamos originalmente esta DataTable no tutorial Criando uma Camada de Acesso a Dados , a CategoriesDataTable
única tinha as três primeiras colunas; a NumberOfProducts
coluna foi adicionada no tutorial Mestre/Detalhes Usando uma Lista com Marcadores de Registros Mestre com uma Lista de Dados de Detalhes.
Conforme discutido em Criando uma Camada de Acesso a Dados, as DataTables no Conjunto de Dados Tipado compõem os objetos de negócios. Os TableAdapters são responsáveis por se comunicar com o banco de dados e preencher os objetos de negócios com os resultados da consulta. O CategoriesDataTable
é preenchido CategoriesTableAdapter
pelo , que tem três métodos de recuperação de dados:
GetCategories()
executa a consulta principal do TableAdapter e retorna osCategoryID
campos ,CategoryName
eDescription
de todos os registros naCategories
tabela. A consulta principal é o que é usado pelos métodos eUpdate
geradosInsert
automaticamente.GetCategoryByCategoryID(categoryID)
retorna osCategoryID
campos ,CategoryName
eDescription
da categoria cujoCategoryID
é igual a categoryID.GetCategoriesAndNumberOfProducts()
- retorna osCategoryID
campos ,CategoryName
eDescription
para todos os registros naCategories
tabela. Também usa uma subconsulta para retornar o número de produtos associados a cada categoria.
Observe que nenhuma dessas consultas retorna a Categories
tabela s Picture
ou BrochurePath
colunas; nem CategoriesDataTable
fornece DataColumn
s para esses campos. Para trabalhar com a imagem e BrochurePath
as propriedades, precisamos primeiro adicioná-las ao CategoriesDataTable
e, em seguida, atualizar a CategoriesTableAdapter
classe para retornar essas colunas.
Adicionando oPicture
eBrochurePath``DataColumn
s
Comece adicionando essas duas colunas ao CategoriesDataTable
. Clique com o botão direito do CategoriesDataTable
mouse no cabeçalho s, selecione Adicionar no menu de contexto e escolha a opção Coluna. Isso criará um novo DataColumn
na DataTable chamado Column1
. Renomeie esta coluna para Picture
. Na janela Propriedades, defina a DataColumn
propriedade s DataType
como System.Byte[]
(essa não é uma opção na lista suspensa; você precisa digitá-la).
Figura 6: Criar um DataColumn
nome Picture
cujo DataType
é System.Byte[]
(clique para exibir a imagem em tamanho real)
Adicione outro DataColumn
ao DataTable, nomeando-o BrochurePath
usando o valor padrão DataType
(System.String
).
Retornando osPicture
valores eBrochurePath
do TableAdapter
Com esses dois DataColumn
s adicionados ao , estamos prontos para atualizar o CategoriesDataTable
CategoriesTableAdapter
. Poderíamos ter esses dois valores de coluna retornados na consulta principal do TableAdapter, mas isso traria de volta os dados binários toda vez que o GetCategories()
método fosse invocado. Em vez disso, vamos atualizar a consulta principal TableAdapter para trazer de volta BrochurePath
e criar um método de recuperação de dados adicional que retorna uma coluna s Picture
de categoria específica.
Para atualizar a consulta principal do TableAdapter, clique com o botão direito do CategoriesTableAdapter
mouse no cabeçalho s e escolha a opção Configurar no menu de contexto. Isso abre o Assistente de Configuração do Adaptador de Tabela, que vimos em vários tutoriais anteriores. Atualize a consulta para trazer de volta o BrochurePath
e clique em Concluir.
Figura 7: Atualizar a lista de colunas na SELECT
instrução para retornar BrochurePath
também (clique para exibir a imagem em tamanho real)
Ao usar instruções SQL ad hoc para o TableAdapter, atualizar a lista de colunas na consulta principal atualiza a lista de colunas para todos os SELECT
métodos de consulta no TableAdapter. Isso significa que o GetCategoryByCategoryID(categoryID)
método foi atualizado para retornar a BrochurePath
coluna, que pode ser o que pretendíamos. No entanto, também atualizou a lista de colunas no GetCategoriesAndNumberOfProducts()
método, removendo a subconsulta que retorna o número de produtos para cada categoria! Portanto, precisamos atualizar a consulta desse SELECT
método. Clique com o botão direito do GetCategoriesAndNumberOfProducts()
mouse no método, escolha Configurar e reverta a SELECT
consulta de volta ao seu valor original:
SELECT CategoryID, CategoryName, Description,
(SELECT COUNT(*)
FROM Products p
WHERE p.CategoryID = c.CategoryID)
as NumberOfProducts
FROM Categories c
Em seguida, crie um novo método TableAdapter que retorna um valor de coluna de Picture
categoria específica. Clique com o botão direito do CategoriesTableAdapter
mouse no cabeçalho s e escolha a opção Adicionar Consulta para iniciar o Assistente de Configuração de Consulta TableAdapter. A primeira etapa deste assistente nos pergunta se queremos consultar dados usando uma instrução SQL ad-hoc, um novo procedimento armazenado ou um existente. Selecione Usar instruções SQL e clique em Avançar. Como retornaremos uma linha, escolha a opção SELECT que retorna linhas da segunda etapa.
Figura 8: Selecione a opção Usar instruções SQL (clique para exibir a imagem em tamanho real)
Figura 9: Como a consulta retornará um registro da tabela Categorias, escolha SELECT que retorna linhas (clique para exibir a imagem em tamanho real)
Na terceira etapa, insira a seguinte consulta SQL e clique em Avançar:
SELECT CategoryID, CategoryName, Description, BrochurePath, Picture
FROM Categories
WHERE CategoryID = @CategoryID
A última etapa é escolher o nome do novo método. Use FillCategoryWithBinaryDataByCategoryID
e GetCategoryWithBinaryDataByCategoryID
para os padrões Preencher uma DataTable e Retornar uma DataTable, respectivamente. Clique em Concluir para concluir o assistente.
Figura 10: Escolher os nomes para os métodos do TableAdapter (clique para exibir a imagem em tamanho completo)
Observação
Depois de concluir o Assistente de Configuração de Consulta do Adaptador de Tabela, você poderá ver uma caixa de diálogo informando que o novo texto de comando retorna dados com esquema diferente do esquema da consulta principal. Em resumo, o assistente está observando que a consulta GetCategories()
principal do TableAdapter retorna um esquema diferente daquele que acabamos de criar. Mas é isso que queremos, então você pode desconsiderar esta mensagem.
Além disso, lembre-se de que, se você estiver usando instruções SQL ad hoc e usar o assistente para alterar a consulta principal do TableAdapter em algum momento posterior, ele modificará a GetCategoryWithBinaryDataByCategoryID
lista de colunas da instrução do SELECT
método para incluir apenas as colunas da consulta principal (ou seja, removerá a Picture
coluna da consulta). Você terá que atualizar manualmente a lista de colunas para retornar a Picture
coluna, semelhante ao que fizemos com o GetCategoriesAndNumberOfProducts()
método anteriormente nesta etapa.
Depois de adicionar os dois DataColumn
s ao CategoriesDataTable
e o GetCategoryWithBinaryDataByCategoryID
método ao CategoriesTableAdapter
, essas classes no Typed DataSet Designer devem se parecer com a captura de tela na Figura 11.
Figura 11: O designer de conjunto de dados inclui as novas colunas e o método
Atualizando a BLL (Camada de Lógica de Negócios)
Com a DAL atualizada, tudo o que resta é aumentar a BLL (Business Logic Layer) para incluir um método para o novo CategoriesTableAdapter
método. Adicione o seguinte método à classe CategoriesBLL
:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable
GetCategoryWithBinaryDataByCategoryID(int categoryID)
{
return Adapter.GetCategoryWithBinaryDataByCategoryID(categoryID);
}
Etapa 5: Carregando um arquivo do cliente para o servidor Web
Ao coletar dados binários, muitas vezes esses dados são fornecidos por um usuário final. Para capturar essas informações, o usuário precisa ser capaz de fazer upload de um arquivo de seu computador para o servidor web. Os dados carregados precisam ser integrados ao modelo de dados, o que pode significar salvar o arquivo no sistema de arquivos do servidor Web e adicionar um caminho ao arquivo no banco de dados ou gravar o conteúdo binário diretamente no banco de dados. Nesta etapa, veremos como permitir que um usuário carregue arquivos de seu computador para o servidor. No próximo tutorial, voltaremos nossa atenção para a integração do arquivo carregado com o modelo de dados.
ASP.NET 2.0 s novo controle da Web FileUpload fornece um mecanismo para os usuários enviarem um arquivo de seu computador para o servidor Web. O controle FileUpload é renderizado como um <input>
elemento cujo type
atributo é definido como file, que os navegadores exibem como uma caixa de texto com um botão Procurar. Clicar no botão Procurar abre uma caixa de diálogo na qual o usuário pode selecionar um arquivo. Quando o formulário é postado, o conteúdo do arquivo selecionado é enviado junto com o postback. No lado do servidor, as informações sobre o arquivo carregado podem ser acessadas por meio das propriedades do controle FileUpload.
Para demonstrar o carregamento de arquivos, abra a FileUpload.aspx
página na BinaryData
pasta, arraste um controle FileUpload da Caixa de Ferramentas para o Designer e defina a propriedade do ID
controle como UploadTest
. Em seguida, adicione um controle Web de botão definindo suas ID
propriedades e Text
e UploadButton
Carregar Arquivo Selecionado, respectivamente. Por fim, coloque um controle Web Label abaixo do Button, limpe sua Text
propriedade e defina sua ID
propriedade como UploadDetails
.
Figura 12: Adicionar um controle FileUpload à página ASP.NET (clique para exibir a imagem em tamanho real)
A Figura 13 mostra essa página quando visualizada por meio de um navegador. Observe que clicar no botão Procurar abre uma caixa de diálogo de seleção de arquivo, permitindo que o usuário escolha um arquivo de seu computador. Depois que um arquivo é selecionado, clicar no botão Carregar Arquivo Selecionado causa um postback que envia o conteúdo binário do arquivo selecionado para o servidor Web.
Figura 13: O usuário pode selecionar um arquivo para carregar de seu computador para o servidor (clique para exibir a imagem em tamanho real)
No postback, o arquivo carregado pode ser salvo no sistema de arquivos ou seus dados binários podem ser trabalhados diretamente por meio de um Stream. Para este exemplo, vamos criar uma ~/Brochures
pasta e salvar o arquivo carregado lá. Comece adicionando a Brochures
pasta ao site como uma subpasta do diretório raiz. Em seguida, crie um manipulador de eventos para o UploadButton
evento s Click
e adicione o seguinte código:
protected void UploadButton_Click(object sender, EventArgs e)
{
if (UploadTest.HasFile == false)
{
// No file uploaded!
UploadDetails.Text = "Please first select a file to upload...";
}
else
{
// Display the uploaded file's details
UploadDetails.Text = string.Format(
@"Uploaded file: {0}<br />
File size (in bytes): {1:N0}<br />
Content-type: {2}",
UploadTest.FileName,
UploadTest.FileBytes.Length,
UploadTest.PostedFile.ContentType);
// Save the file
string filePath =
Server.MapPath("~/Brochures/" + UploadTest.FileName);
UploadTest.SaveAs(filePath);
}
}
O controle FileUpload fornece uma variedade de propriedades para trabalhar com os dados carregados. Por exemplo, a HasFile
propriedade indica se um arquivo foi carregado pelo usuário, enquanto a FileBytes
propriedade fornece acesso aos dados binários carregados como uma matriz de bytes. O Click
manipulador de eventos começa garantindo que um arquivo tenha sido carregado. Se um arquivo tiver sido carregado, o Rótulo mostrará o nome do arquivo carregado, seu tamanho em bytes e seu tipo de conteúdo.
Observação
Para garantir que o usuário carregue um arquivo, você pode verificar a HasFile
propriedade e exibir um aviso se for false
, ou você pode usar o controle RequiredFieldValidator em vez disso.
O FileUpload salva SaveAs(filePath)
o arquivo carregado no filePath especificado. filePath deve ser um caminho físico (C:\Websites\Brochures\SomeFile.pdf
) em vez de um caminho virtual (/Brochures/SomeFile.pdf
). O Server.MapPath(virtPath)
método usa um caminho virtual e retorna seu caminho físico correspondente. Aqui, o caminho virtual é ~/Brochures/fileName
, onde fileName é o nome do arquivo carregado. Consulte o método Server.MapPath para obter mais informações sobre caminhos virtuais e físicos e como usar Server.MapPath
o .
Depois de concluir o manipulador de Click
eventos, reserve um momento para testar a página em um navegador. Clique no botão Procurar e selecione um arquivo do disco rígido e, em seguida, clique no botão Carregar arquivo selecionado. O postback enviará o conteúdo do arquivo selecionado para o servidor Web, que exibirá informações sobre o arquivo antes de salvá-lo na ~/Brochures
pasta. Depois de carregar o arquivo, retorne ao Visual Studio e clique no botão Atualizar no Gerenciador de Soluções. Você deve ver o arquivo que acabou de enviar na pasta ~/Brochuras!
Figura 14: O arquivo EvolutionValley.jpg
foi carregado no servidor Web (clique para exibir a imagem em tamanho real)
Figura 15: EvolutionValley.jpg
foi salvo na ~/Brochures
pasta
Sutilezas ao salvar arquivos carregados no sistema de arquivos
Há várias sutilezas que devem ser abordadas ao salvar o upload de arquivos no sistema de arquivos do servidor Web. Primeiro, há a questão da segurança. Para salvar um arquivo no sistema de arquivos, o contexto de segurança no qual a página ASP.NET está sendo executada deve ter permissões de gravação. O servidor Web de desenvolvimento do ASP.NET é executado no contexto de sua conta de usuário atual. Se você estiver usando o IIS (Serviços de Informações da Internet) da Microsoft como servidor Web, o contexto de segurança dependerá da versão do IIS e de sua configuração.
Outro desafio de salvar arquivos no sistema de arquivos gira em torno de nomear os arquivos. Atualmente, nossa página salva todos os arquivos carregados no ~/Brochures
diretório usando o mesmo nome do arquivo no computador do cliente. Se o usuário A carregar um folheto com o nome Brochure.pdf
, o arquivo será salvo como ~/Brochure/Brochure.pdf
. Mas e se algum tempo depois o usuário B carregar um arquivo de brochura diferente que tenha o mesmo nome de arquivo (Brochure.pdf
)? Com o código que temos agora, o arquivo do usuário A será substituído pelo upload do usuário B.
Existem várias técnicas para resolver conflitos de nome de arquivo. Uma opção é proibir o upload de um arquivo se já existir um com o mesmo nome. Com essa abordagem, quando o usuário B tenta carregar um arquivo chamado Brochure.pdf
, o sistema não salva o arquivo e, em vez disso, exibe uma mensagem informando ao usuário B para renomear o arquivo e tentar novamente. Outra abordagem é salvar o arquivo usando um nome de arquivo exclusivo, que pode ser um GUID (identificador global exclusivo) ou o valor das colunas de chave primária do registro de banco de dados correspondente (supondo que o upload esteja associado a uma linha específica no modelo de dados). No próximo tutorial, exploraremos essas opções com mais detalhes.
Desafios envolvidos com quantidades muito grandes de dados binários
Esses tutoriais pressupõem que os dados binários capturados são modestos em tamanho. Trabalhar com quantidades muito grandes de arquivos de dados binários com vários megabytes ou mais apresenta novos desafios que estão além do escopo desses tutoriais. Por exemplo, por padrão, ASP.NET rejeitará uploads de mais de 4 MB, embora isso possa ser configurado por meio do <httpRuntime>
elemento em Web.config
. O IIS também impõe suas próprias limitações de tamanho de upload de arquivo. Além disso, o tempo necessário para carregar arquivos grandes pode exceder os 110 segundos padrão ASP.NET aguardará uma solicitação. Também há problemas de memória e desempenho que surgem ao trabalhar com arquivos grandes.
O controle FileUpload é impraticável para uploads de arquivos grandes. À medida que o conteúdo do arquivo está sendo postado no servidor, o usuário final deve aguardar pacientemente sem qualquer confirmação de que o upload está progredindo. Isso não é tanto um problema ao lidar com arquivos menores que podem ser carregados em alguns segundos, mas pode ser um problema ao lidar com arquivos maiores que podem levar minutos para serem carregados. Há uma variedade de controles de upload de arquivos de terceiros que são mais adequados para lidar com uploads grandes e muitos desses fornecedores fornecem indicadores de progresso e gerenciadores de upload ActiveX que apresentam uma experiência de usuário muito mais refinada.
Se seu aplicativo precisar lidar com arquivos grandes, você precisará investigar cuidadosamente os desafios e encontrar soluções adequadas para suas necessidades específicas.
Resumo
A criação de um aplicativo que precisa capturar dados binários apresenta vários desafios. Neste tutorial, exploramos os dois primeiros: decidir onde armazenar os dados binários e permitir que um usuário carregue conteúdo binário por meio de uma página da web. Nos próximos três tutoriais, veremos como associar os dados carregados a um registro no banco de dados, bem como exibir os dados binários ao lado de seus campos de dados de texto.
Boa programação!
Leitura Adicional
Para obter mais informações sobre os tópicos discutidos neste tutorial, consulte os seguintes recursos:
- Usando tipos de dados de grande valor
- Inícios rápidos do controle FileUpload
- O controle de servidor FileUpload do ASP.NET 2.0
- O lado negro dos uploads de arquivos
Sobre o autor
Scott Mitchell, autor de sete livros ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos especiais a
Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Teresa Murphy e Bernadette Leigh. Interessado em revisar meus próximos artigos do MSDN? Em caso afirmativo, envie-me uma mensagem para mitchell@4GuysFromRolla.com.