I have an API server method that accept getting files as BASE64. Getting request like this:
{
file: "-BASE 64 HERE-"
}
I want that my server will get this file and store it on Azure Storage. So, I running this code:
var blob = container.GetBlockBlobReference("file.zip");
var buffer = Convert.FromBase64String(Model.File);
await blob.UploadFromByteArrayAsync(buffer, 0, buffer.Length);
It's working, but inefficient.
Why? Because the same bytes have two instances in my main memory: as byte array + as stream.
I wounder if it possible to upload the BASE64 as text, and letting the server understand that this is BASE64 - which will be treated like a file.
In that way I will upload the text directly without convert it to stream.
Is this possible?
May be linked to this thread
Thanks.
Can't you just use UploadFromStreamAsync?
Related
I'm working on an endpoint to uploading a file and sending it to WCF Service.
I have an endpoint that accept a one file in form-data. A user can upload up to 50 files, but files are uploaded one by one (one at the time). Each file can be up to 5MB. So, in the code I read the file as Stream, and I must send a file to WCF Service as byte array.
That’s the problem. I don’t want to allocate 5MB array in the memory just to send it to WCF Service. 50 files * 5MB = 250MB. It’s a lot.
Not-optimised code looks like this below.
public async Task<IHttpActionResult> UploadFile()
{
MultipartMemoryStreamProvider multipartMemoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
HttpContent file = multipartMemoryStreamProvider.Contents.GetFormValue("file");
int length = (int) file.Headers.ContentLength;
byte[] fileContent = new byte[length]; // allocating up to 5MB :(
using (Stream stream = await file.ReadAsStreamAsync())
{
await stream.ReadAsync(fileContent, 0, length);
}
await _documentService.UploadAsync("filename", fileContent);
}
I tried to use ArrayPool, and it worked great, but ArrayPool gives me an array that has minimum of asked bytes. So, I was sending more bytes that I wanted (e.g. for 420KB files I received 512KB array). I can use ArrayPool.Create(). However, I don’t want to end up with huge number of pools.
Also, I checked Array.Resize (https://learn.microsoft.com/en-us/dotnet/api/system.array.resize?view=netframework-4.8) but it copies elements from old array to new array (allocated again the same array).
Span is not useful because .ToArray() method will allocate a new byte array.
Do you have any idea how to create byte array without allocating?
There is no way to "create byte array without allocating". As long as API requires array you must create new one as size is part of the instance (the only optimization you can do is to reuse arrays of the same size).
So your options are:
live with it. If memory allocation is a problem you can force garbage collection.
change the API to be either streaming or support partial uploads or use regular POST instead of WCF methods.
I am uploading an .mp3 file via FTP code using C#, the file is uploaded successfully on server but when i bind to a simple audio control or directly view in browser it does not work as expected, whereas when i upload manually on the server it works perfectly.
Code:
var inputStream = FileUpload1.PostedFile.InputStream;
byte[] fileBytes = new byte[inputStream.Length];
inputStream.Read(fileBytes, 0, fileBytes.Length);
Note: When i view the file in Firefox it shows MIME type is not supported.
Thanks!
You're reading the file as a string then using UTF8 encoding to turn it into bytes. If you do that, and the file contains any binary sequence that doesn't code to a valid UTF8 value, parts of the data stream will simply get discarded.
Instead, read it directly as bytes. Don't bother with the StreamReader. Call the Read() method on the underlying stream. Example:
var inputStream = FileUpload1.PostedFile.InputStream
byte[] fileBytes = new byte[inputStream.Length];
inputStream.Read(fileBytes, 0, fileStream.Length);
Im making this website,where the user has a form in which they can choose a file from their computer,and upload it, but i don't know how i can use it. I'm using MVC and a Web Service also in C# where im handling the connection to the Database,where I have to save the file.The file can be a pdf,word or an image.
So the question is,how can I save it and also check its size.Thank you
You can use the ContentLength property of HttpPostedFileBase to get the size of the file -
https://msdn.microsoft.com/en-us/library/system.web.httppostedfilebase.contentlength(v=vs.110).aspx
Then save the InputStream to a byte array
using (MemoryStream stream = new MemoryStream())
{
file.InputStream.CopyTo(stream);
bytes = stream.ToArray();
}
Next assign the byte array to a SqlDbType.VarBinary stored procedure parameter to save it back to the database - assuming this is SQL Server.
We have an IOS application which send images to a asp.net web api application. So we convert images to Base64 then we send it to the web service as a string .
The problem is that the size of the image is big so the conversion to base64 takes a lot of time and the size of the result string is bigger than the initial image's size.
I need to know :
If another better way , instead of conversion to Base64, exists to convert the image before calling the web service
I used Gzip to compress/decompress an array of bytes like this :
static byte[] Compress(byte[] data)
{
using (var compressedStream = new MemoryStream())
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
{
zipStream.Write(data, 0, data.Length);
zipStream.Close();
return compressedStream.ToArray();
}
}
Is it possible to convert image to array of bytes in IOS part then call the web service ? Or expose an object like compressedStream or GZipStream as a service argument?
Thanks,
it is possible to convert the image to a byte array, here's an SO answer which touches on that : how to convert byte array to image in ios
The biggest question however is this : do you actually need the image that big? You need to consider that the service will get slow once you have multiple users doing this and will more than likely grind to a halt which will make your app difficult/ slow to use.
You might want to consider reducing the image before sending it over. You can reduce the size, the quality and just make it smaller, then send the result over the wire.
Here is another SO post which touches on this : What's the easiest way to resize/optimize an image size with the iPhone SDK?
Of course if you are using xamarin and c# to build your app then it's even easier and you can find samples of code doing both these things.
I have a flash app which sends raw data for a jpg image to a particular url Send.aspx . In Send.aspx I am using request.binaryread() to get the total request length and then read in the data to a byte array.
Then I am writing the data as jpg file to the server. The code is given below:
FileStream f = File.Create(Server.MapPath("~") + "/plugins/handwrite/uploads/" + filename);
byte[] data = Request.BinaryRead(Request.TotalBytes);
f.Write(data, 0, data.Length);
f.Close();
The file is getting created but there is no image in it. It always shows up as empty in any graphic viewer. What part am I missing. Am I supposed to use jpg encoding first before writing it to file? Thanks in advance
Well, you should use a using statement for your file stream, but other than that it looks okay to me.
A few suggestions for how to proceed...
Is it possible that the client isn't providing the data properly? Perhaps it's providing it as base64-encoded data?
Have you already read some data from the request body? (That could mess things up.)
I suggest you look closely at what you end up saving vs the original file:
Are they the same length? If not, which is longer?
If they're the same length, do their MD5 sums match?
If you look at both within a binary file editor, do they match at all? Any obvious differences?