I have 2 methods to upload files to Blob Storage. 'UploadFileToContainer' is working fine, and i get files with data in container. The problem is 'UploadOrReplaceFileToContainer', where it's not possible to use file.Position = 0, returning the follow error:
System.NotSupportedException: 'Specified method is not supported.'
Can someone help?
public void UploadFileToContainer(Stream file, string fileName, string userId)
{
string uniqueFileName = GetFileNameUniqueId(fileName);
BlobClient blob = _container.GetBlobClient(fileName);
blob.Upload(file);
file.Position = 0;
BlobClient blob2 = _containerbackup.GetBlobClient(uniqueFileName);
blob2.Upload(file);
_log.LogFileUpload(fileName, uniqueFileName, userId, DateTime.Now);
}
public int UploadOrReplaceFileToContainer(Stream file, string fileName, string userId)
{
string uniqueFileName = GetFileNameUniqueId(fileName);
if (_container.GetBlobs().Any(b => b.Name == fileName))
{
_container.DeleteBlob(fileName);
}
BlobClient blob = _container.GetBlobClient(fileName);
blob.Upload(file);
file.Position = 0; //here is where i get the error
BlobClient blob2 = _containerbackup.GetBlobClient(uniqueFileName);
blob2.Upload(file);
int fileUploadId = _log.LogFileUpload(fileName, uniqueFileName, userId, DateTime.Now);
return fileUploadId;
}
You are getting this error suppose your stream type canseek type is false. You could create a new MemoryStream and copy the stream to the MemoryStream then seek it or just set the position.
System.IO.MemoryStream blobstream = new System.IO.MemoryStream();
inputblob.CopyTo(blobstream);
blobstream.Position = 0;
//blobstream.Seek(0, SeekOrigin.Begin);
blob.Upload(blobstream);
Also you could refer to other discussion about this:read a Stream and reset its position to zero.
Related
I'm uploading files to Azure Blob Storage with the .Net package specifying the encoding iso-8859-1. The stream seems ok in Memory but when I upload to the blob storage it ends with corrupted characters that seems that could not be converted to that encoding. It would seem as if the file gets storaged in a corrupted state and when I download it again and check it the characters get all messed up. Here is the code I'm using.
public static async Task<bool> UploadFileFromStream(this CloudStorageAccount account, string containerName, string destBlobPath, string fileName, Stream stream, Encoding encoding)
{
if (account is null) throw new ArgumentNullException(nameof(account));
if (string.IsNullOrEmpty(containerName)) throw new ArgumentException("message", nameof(containerName));
if (string.IsNullOrEmpty(destBlobPath)) throw new ArgumentException("message", nameof(destBlobPath));
if (stream is null) throw new ArgumentNullException(nameof(stream));
stream.Position = 0;
CloudBlockBlob blob = GetBlob(account, containerName, $"{destBlobPath}/{fileName}");
blob.Properties.ContentType = FileUtils.GetFileContentType(fileName);
using var reader = new StreamReader(stream, encoding);
var ct = await reader.ReadToEndAsync();
await blob.UploadTextAsync(ct, encoding ?? Encoding.UTF8, AccessCondition.GenerateEmptyCondition(), new BlobRequestOptions(), new OperationContext());
return true;
}
This is the file just before uploading it
<provinciaDatosInmueble>Sevilla</provinciaDatosInmueble>
<inePoblacionDatosInmueble>969</inePoblacionDatosInmueble>
<poblacionDatosInmueble>Valencina de la Concepción</poblacionDatosInmueble>
and this is the file after the upload
<provinciaDatosInmueble>Sevilla</provinciaDatosInmueble>
<inePoblacionDatosInmueble>969</inePoblacionDatosInmueble>
<poblacionDatosInmueble>Valencina de la Concepci�n</poblacionDatosInmueble>
The encoding I send is ISO-5589-1 in the parameter of the encoding. Anybody knows why Blob Storage seems to ignore the encoding I'm specifying? Thanks in advance!
We could able to achieve this using Azure.Storage.Blobs instead of WindowsAzure.Storage which is a legacy Storage SDK. Below is the code that worked for us.
class Program
{
static async Task Main(string[] args)
{
string sourceContainerName = "<Source_Container_Name>";
string destBlobPath = "<Destination_Path>";
string fileName = "<Source_File_name>";
MemoryStream stream = new MemoryStream();
BlobServiceClient blobServiceClient = new BlobServiceClient("<Your_Connection_String>");
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(sourceContainerName);
BlobClient blobClientSource = containerClient.GetBlobClient(fileName);
BlobClient blobClientDestination = containerClient.GetBlobClient(destBlobPath);
// Reading From Blob
var line =" ";
if (await blobClientSource.ExistsAsync())
{
var response = await blobClientSource.DownloadAsync();
using (StreamReader streamReader = new StreamReader(response.Value.Content))
{
line = await streamReader.ReadToEndAsync();
}
}
// Writing To Blob
var content = Encoding.UTF8.GetBytes(line);
using (var ms = new MemoryStream(content))
blobClientDestination.Upload(ms);
}
}
RESULT:
can I append Images byte... ? I tried that but not works.. its increase the size but not reflect images.. its always return first image that I append first.. So Please help how can I append images ? json/text files are working fine but I m stuck on append image..
So,Please Help how can i do that..
Here is my code
CloudAppendBlob cloudAppendBlob = cloudBlobContainer.GetAppendBlobReference(fileName);
bool exist = await cloudAppendBlob.ExistsAsync();
if(!exist)
{
await cloudAppendBlob.CreateOrReplaceAsync();
}
cloudAppendBlob.Properties.ContentType = fileType;
stream.Position = 0;
await cloudAppendBlob.AppendBlockAsync(stream);
You can not append images with the same name. If you do that, it will replace the image file with the same name. If you upload another image then it would create a new image as per the uploaded one. Try the code below.
private CloudBlobContainer blobContainer;
public AzureBlobHelper()
{
try
{
// Get azure table storage connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
blobContainer = cloudBlobClient.GetContainerReference(CloudConfigurationManager.GetSetting("StorageContainer"));
// Create the container and set the permission
if (blobContainer.CreateIfNotExists())
{
blobContainer.SetPermissions(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
}
);
}
}
catch (Exception ExceptionObj)
{
// throw ExceptionObj;
}
}
public string UploadFile(string FileName, string LocalPath, string AzureBlobPath, string ContentType = "")
{
string AbsoluteUri;
try
{
CloudBlockBlob blockBlob;
// Create a block blob
blockBlob = blobContainer.GetBlockBlobReference(AzureBlobPath + FileName);
// Set the object's content type
blockBlob.Properties.ContentType = ContentType;
blockBlob.UploadFromFile(LocalPath);
// get file uri
AbsoluteUri = blockBlob.Uri.AbsoluteUri;
}
catch (Exception ExceptionObj)
{
throw ExceptionObj;
}
return AbsoluteUri;
}
I am trying to upload the file that I have stored in MemoryStream using the following code.
private static void SaveStream(MemoryStream stream, string fileName)
{
var blobStorageService = new BlobStorageService();
UploadBlob(stream, fileName);
}
public void UploadBlob(MemoryStream fileStream,string fileName)
{
var blobContainer = _blobServiceClient.GetBlobContainerClient(Environment
.GetEnvironmentVariable("ContainerName"));
var blobClient = blobContainer.GetBlobClient(fileName);
blobClient.Upload(fileStream); <--- Error Message
}
Error Message: System.ArgumentException: 'content.Position must be less than content.Length.Please set content.Position to the start of the data to upload.'
This happened because the current position is at the end of the stream. You can set the position to the start of the stream before uploading
var blobClient = blobContainer.GetBlobClient(fileName);
fileStream.Position =0;
blobClient.Upload(fileStream)
I have zipped a file and upload to a blob in azure , but I am unable to download it after unzipping it. I have tried the below code but it is throwing error:
public FileStream Download(string strPath)
{
Stream fs = GetFile(strPath);
using (ZipArchive zip = new ZipArchive(fs))
{
var entry = zip.Entries.First();
var memoryStream = entry.Open();
string filename = "Report_" + GetUploadTime();
using (var fileStream = new FileStream(filename,
FileMode.CreateNew,
FileAccess.ReadWrite))
{
memoryStream.CopyTo(fileStream); // fileStream is not populated
return fileStream;
}
}
}
System.UnauthorizedAccessException occurred in mscorlib.dll but was not handled in user code, I do not want to create any folder or keep it anywhere just unzip and download how to do it.
public Stream GetFile(string strPath)
{
try
{
var filename = Path.GetFileName(strPath);
string account = ConfigurationManager.AppSettings["BlobContainer"];
string key = ConfigurationManager.AppSettings["BlobKey"];
string connectionString =
string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
account, key);
CloudStorageAccount storageAccount =
CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("reportportalblob");
CloudBlockBlob blob = container.GetBlockBlobReference(filename);
Stream blobStream = blob.OpenRead();
return blobStream;
}
catch (Exception)
{
// download failed
// handle exception
throw;
}
}
I have search for some code but I am not getting anything, please help.
We could get the unzip stream with following code.
public MemoryStream GetFile(string strPath)
{
try
{
var filename = Path.GetFileName(strPath);
string account = ConfigurationManager.AppSettings["accountName"];
string key = ConfigurationManager.AppSettings["accountKey"];
string containerName = "test";
string connectionString =$"DefaultEndpointsProtocol=https;AccountName={account};AccountKey={key}";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
CloudBlockBlob blob = container.GetBlockBlobReference(filename);
MemoryStream memory = new MemoryStream();
blob.DownloadToStream(memory);
var zipArchive = new ZipArchive(memory, ZipArchiveMode.Read, true);
var entry = zipArchive.Entries.First();
if (entry != null)
{
var stream = entry.Open();
memory = new MemoryStream();
stream.CopyTo(memory);
memory.Position = 0;
return memory;
}
return null;
}
catch (Exception)
{
// download failed
// handle exception
throw;
}
}
If we want to down to file, then we could use File.WriteAllBytes(strPath,memory.ToArray()); or fileStream.Write(memory.ToArray(),0,memory.ToArray().Length-1);
public void Download(string strPath)
{
var memory = GetFile(strPath);
string filename = "Report_" + DateTime.Now;
var fileStream = new FileStream(filename,
FileMode.CreateNew,
FileAccess.ReadWrite);
// File.WriteAllBytes(strPath,memory.ToArray());
fileStream.Write(memory.ToArray(),0,memory.ToArray().Length-1);
}
I am using FileStream.Create to upload a .csv file onto a server and then read it into a SQL database. Once it is read in, I just delete the file from the folder that it was written to. The goal is to just get the file into the database. This would run fine locally, but I cannot get write access on the new server so I get an UnauthorizedAccessException. I don't think that it is necessary to upload the file to the server to read it into the SQL table, but I am having trouble adjusting the code.
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
var inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
var cc = new CsvContext();
var filePath = uploadFile(csvFile.InputStream);
var model = cc.Read<Credit>(filePath, inputFileDescription);
try
{
var entity = new Entities();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
Id = item.Id,
Amount = item.Amount,
Date = item.Date,
Number = item.Number,
ReasonId = item.ReasonId,
Notes = item.Notes
};
entity.TemporaryCsvUploads.Add(tc);
}
entity.SaveChanges();
System.IO.File.Delete(filePath);
Here is the uploadFile method:
private string uploadFile(Stream serverFileStream)
{
const string directory = "~/Content/CSVUploads";
var directoryExists = Directory.Exists(Server.MapPath(directory));
if (!directoryExists)
{
Directory.CreateDirectory(Server.MapPath(directory));
}
var targetFolder = Server.MapPath(directory);
var filename = Path.Combine(targetFolder, Guid.NewGuid() + ".csv");
try
{
const int length = 256;
var buffer = new byte[length];
// write the required bytes
using (var fs = new FileStream(filename, FileMode.Create))
{
int bytesRead;
do
{
bytesRead = serverFileStream.Read(buffer, 0, length);
fs.Write(buffer, 0, bytesRead);
} while (bytesRead == length);
}
serverFileStream.Dispose();
return filename;
}
catch (Exception)
{
return string.Empty;
}
}
To sum it up, I am uploading a .csv file to a temporary location, reading it into an object, reading it into a database, then deleting the .csv file out of the temporary location. I am using Linq2Csv to create the object. Can I do this without uploading the file to the server (because I can't get write access)?
According to http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library,
you can read from a StreamReader
Read<T>(StreamReader stream)
Read<T>(StreamReader stream, CsvFileDescription fileDescription)
You can probably use a streamreader (or a stringbuilder) to create your file instead of a csv - Write StringBuilder to Stream
How to take a stringbuilder and convert it to a streamReader?
and then send that to your CSVContext?