Retrieve binary data from S3 storage through AWS.NET in C# - c#

I've tested most of the included samples in the AWS SDK for .NET and they all works fine.
I can PUT objects, LIST objects and DELETE objects in a bucket, but... lets say I delete the original and want to sync those files missing locally?
I would like to make a GET object (by key/name and bucket ofcause). I can find the object, but how do I read the binary data from S3 through the API?
Do I have to write my own SOAP wrapper for this or is there some kinda sample for this out "here" ? :o)
In hope of a sample. It does not have to tollerate execeptions etc. I just need to see the main parts that connects, retreives and stores the file back on my ASP.net or C# project.
Anyone???

Here is an example:
string bucketName = "bucket";
string key = "some/key/name.bin";
string dest = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "name.bin");
using (AmazonS3 client = Amazon.AWSClientFactory.CreateAmazonS3Client(AWSAccessKeyID, AWSSecretAccessKeyID))
{
GetObjectRequest getObjectRequest = new GetObjectRequest().WithBucketName(bucketName).WithKey(key);
using (S3Response getObjectResponse = client.GetObject(getObjectRequest))
{
if (!File.Exists(dest))
{
using (Stream s = getObjectResponse.ResponseStream)
{
using (FileStream fs = new FileStream(dest, FileMode.Create, FileAccess.Write))
{
byte[] data = new byte[32768];
int bytesRead = 0;
do
{
bytesRead = s.Read(data, 0, data.Length);
fs.Write(data, 0, bytesRead);
}
while (bytesRead > 0);
fs.Flush();
}
}
}
}
}

Related

How to upload a file from a MemoryStream to an FTP server

I created a simple application that collects form data, generates an XML in memory as a MemoryStream object, and and delivers the XML to a server using SMB. The delivery method is simple for SMB:
var outputFile = new FileStream($#"{serverPath}\{filename}.xml", FileMode.Create);
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = stream.Read(buffer, 0, Length);
while (bytesRead > 0)
{
outputFile.Write(buffer, 0, bytesRead);
bytesRead = stream.Read(buffer, 0, Length);
}
However, I need to create an alternative delivery method using FTP (with credentials). I don't want to rewrite my XML method, as creating it in memory saves writing to disk which has been a problem in our environment in the past.
I have not been able to find any examples that explain (for a person of very limited coding ability) how such a thing may be accomplished.
Generally when I have need to upload a file to an FTP server, I use something like this:
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential("user", "pass");
client.UploadFile(uri, WebRequestMethods.Ftp.UploadFile, filename.xml);
}
Can this be adapted to upload from a MemoryStream instead of a file on disk?
If not, what other way could I upload a MemoryStream to an FTP server?
Either use FtpWebRequest, as you can see in Upload a streamable in-memory document (.docx) to FTP with C#?:
WebRequest request =
WebRequest.Create("ftp://ftp.example.com/remote/path/filename.xml");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
using (Stream ftpStream = request.GetRequestStream())
{
memoryStream.CopyTo(ftpStream);
}
or use WebClient.OpenWrite (as you can also see in the answer by #Neptune):
using (var webClient = new WebClient())
{
const string url = "ftp://ftp.example.com/remote/path/filename.xml";
using (Stream uploadStream = client.OpenWrite(url))
{
memoryStream.CopyTo(uploadStream);
}
}
Equivalently, your existing FileStream code can be simplified to:
using (var outputFile = File.Create($#"{serverPath}\{filename}.xml"))
{
stream.CopyTo(outputFile);
}
Though obviously, even better would be to avoid the intermediate MemoryStream and write the XML directly to FileStream and WebRequest.GetRequestStream (using their common Stream interface).
You can use the methods OpenWrite/OpenWriteAsync to get a stream that you can write to from any source (stream/array/...etc.)
Here is an example using OpenWrite to write from a MemoryStream:
var sourceStream = new MemoryStream();
// Populate your stream with data ...
using (var webClient = new WebClient())
{
using (Stream uploadStream = client.OpenWrite(uploadUrl))
{
sourceStream.CopyTo(uploadStream);
}
}

Cannot create DotNetZip ZipFile from file download via HTTP Response

I am try to download a zip file via a url to extract files from. I would rather not have to save it a temp file (which works fine) and rather keep it in memory - it is not very big. For example, if I try to download this file:
http://phs.googlecode.com/files/Download%20File%20Test.zip
using this code:
using Ionic.Zip;
...
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.ContentLength > 0)
{
using (MemoryStream zipms = new MemoryStream())
{
int bytesRead;
byte[] buffer = new byte[32768];
using (Stream stream = response.GetResponseStream())
{
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
zipms.Write(buffer, 0, bytesRead);
ZipFile zip = ZipFile.Read(stream); // <--ERROR: "This stream does not support seek operations. "
}
using (ZipFile zip = ZipFile.Read(zipms)) // <--ERROR: "Could not read block - no data! (position 0x00000000) "
using (MemoryStream txtms = new MemoryStream())
{
ZipEntry csentry= zip["Download File Test.cs"];
csentry.Extract(txtms);
txtms.Position = 0;
using (StreamReader reader = new StreamReader(txtms))
{
string csentry = reader.ReadToEnd();
}
}
}
}
...
Note where i flagged the errors I am receiving. With the first one, it does not like the System.Net.ConnectStream. If I comment that line out and allow it to hit the line where I note the second error, it does not like the MemoryStream. I did see this posting: https://stackoverflow.com/a/6377099/1324284 but I am having the same issues that others mention about not having more then 4 overloads of the Read method so I cannot try the WebClient.
However, if I do everything via a FileStream and save it to a temp location first, then point ZipFile.Read at that temp location, everything works including extracting any contained files into a MemoryStream.
Thanks for any help.
You need to Flush() your MemoryStream and set the Position to 0 before you read from it, otherwise you are trying to read from the current position (where there is nothing).
For your code:
ZipFile zip;
using (Stream stream = response.GetResponseStream())
{
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
zipms.Write(buffer, 0, bytesRead);
zipms.Flush();
zipms.Position = 0;
zip = ZipFile.Read(zipms);
}

Download multiple Mp3 files from different urls as zip archive in asp.Net

I am working on a .Net Application in which i need to add multiple mp3 files to a zip archive and download the zip archive locally. The mp3 files are on different urls ad are not hosted or stored on my server. Which library is good for such thing. I tried using SharpLipZip but failed. Here is my code which i am currently trying to use with sharpziplib. All the code is executed but browser doesnt download.
string[] fileURLs = new string[] { "http://www.musicimpressions.com/demos_mp3g/d_RE41843.mp3", "http://media.archambault.ca/sample/6/2/B/0/62B0CC2D91D4357D6477845E967AF9BA/00000000000000027923-256K_44S_2C_cbr1x_clipped.mp3" };
Response.AddHeader("Content-Disposition", "attachment; filename=CallRecordings.zip");
Response.ContentType = "application/x-zip-compressed";
ZipOutputStream zipStream = new ZipOutputStream(Response.OutputStream);
zipStream.SetLevel(3);
byte[] buffer = new byte[10485760];
foreach (string url in fileURLs)
{
Stream fileStream = null;
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
fileStream = fileResp.GetResponseStream();
byte[] fileBytes = ReadStream(fileStream);
ZipEntry fileEntry = new ZipEntry(ZipEntry.CleanName(url));
fileEntry.Size = fileBytes.Length;
zipStream.PutNextEntry(fileEntry);
zipStream.Write(fileBytes, 0, fileBytes.Length);
Response.Flush();
fileStream.Close();
}
zipStream.Finish();
zipStream.Flush();
zipStream.Close();
Response.Flush();
Response.End();
The definition of ReadStream is as follows.
public static byte[] ReadStream(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Well, thats the same thing which I am also building for my website, anyhow i was trying to look for the zip file structure first to create the zip file manually instead of using any other library. Until now, i am only able to get the structure of the zip file :
https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html
Here, it mentions that you need to have the CRC32 of the file first which is being appended to the zip file, so thats the tricky part in my side. Let me know once you gets any updates for the same.
Good Luck :)

c# upload in real time from client to server to amazon s3

Good morning, I have an desktop app that uploads files to a WCF service and then WCF Service uploads to Amazon S3.
This is my WCF method that receives the file and uploads to S3.
public void UploadFile(RemoteFileInfo request)
{
config = new AmazonS3Config();
config.CommunicationProtocol = Protocol.HTTP;
accessKeyID = "XXXXXXX";
secretAccessKeyID = "YYYYYYYY";
client = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKeyID, secretAccessKeyID, config);
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
using (System.IO.MemoryStream writeStream = new System.IO.MemoryStream())
{
do
{
// read bytes from input stream
int bytesRead = request.FileByteStream.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
// simulates slow connection
System.Threading.Thread.Sleep(3);
// write bytes to output stream
writeStream.Write(buffer, 0, bytesRead);
} while (true);
// report end
Console.WriteLine("Done!");
// start the uploading to S3
PutObjectRequest fileRequest = new PutObjectRequest();
fileRequest.WithInputStream(writeStream);
fileRequest.Key = "testfile.pdf";
fileRequest.WithBucketName("tempbucket");
fileRequest.CannedACL = S3CannedACL.Private;
fileRequest.StorageClass = S3StorageClass.Standard;
client.PutObject(fileRequest);
writeStream.Close();
}
}
On my client I get the progress in real time when upload the file to the WCF Service but when I get the 100% complete it doesnt mean that the file has already uploaded to S3, so I would like to know if its possible to being uploading the file to S3 while Im writing the stream (inside of the using
(System.IO.MemoryStream writeStream = new System.IO.MemoryStream())
{
Is this possible? Any guideline on how to do it?
Appreciate in advance.
You can use InputStream property of PutObjectRequest
public void UploadFile(RemoteFileInfo request)
{
config = new AmazonS3Config();
config.CommunicationProtocol = Protocol.HTTP;
accessKeyID = "XXXXXXX";
secretAccessKeyID = "YYYYYYYY";
client = Amazon.AWSClientFactory.CreateAmazonS3Client(accessKeyID,secretAccessKeyID,config);
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
PutObjectRequest fileRequest = new PutObjectRequest();
fileRequest.Key = "testfile.pdf";
fileRequest.WithBucketName("tempbucket");
fileRequest.CannedACL = S3CannedACL.Private;
fileRequest.StorageClass = S3StorageClass.Standard;
using (fileRequest.InputStream = new System.IO.MemoryStream())
{
do
{
// read bytes from input stream
int bytesRead = request.FileByteStream.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
// simulates slow connection
System.Threading.Thread.Sleep(3);
// write bytes to output stream
fileRequest.InputStream.Write(buffer, 0, bytesRead);
} while (true);
// report end
Console.WriteLine("Done!");
client.PutObject(fileRequest);
}
}
I would recommend uploading the file to the WCF as chunks instead of a stream. I did so and it works just fine. also you need to return a message of the actual bytes written to the amazon later on you can increase the progress bar based on that. I know it will cause you to write a while loop in the client application but it will help you to show the progress with 100% accuracy for large files. Your WCF function should take the parameter like these
[DataContract]
class RemoteFileInfo
{
[DataMember]
Byte[] myChunk;
[DataMember]
long myOffset;
// other stuff you think you need to be sent each time.
}

How to save MP3 file from the internet on Windows Phone 7?

I'm trying to download and save an .mp3 file from the internet, but got stuck with stream from the external link:
private void saveSound()
{
IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication();
using (var fs = new IsolatedStorageFileStream("123.mp3", FileMode.Create, iso))
{
//Here should be this Stream from the Internet...
//Uri: "http://my-site.com/mega-popular-song.mp3"
StreamResourceInfo rs = new StreamResourceInfo(stream, "audio/mpeg");
int count = 0;
byte[] buffer = new byte[4096];
while (0 < (count = rs.Stream.Read(buffer, 0, buffer.Length)))
{
fs.Write(buffer, 0, count);
}
fs.Close();
}
}
What should this stream look like? What is the best way to download and save .mp3 files?
I'm sure this article gets you there. Like Bob mentioned, you'll have to use a WebClient. Basically this is the code that does the magic:
wc.OpenReadCompleted += ((s, args) =>
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(fileName))
store.DeleteFile(fileName);
using (var fs = new IsolatedStorageFileStream(fileName, FileMode.Create, store))
{
byte[] bytesInStream = new byte[args.Result.Length];
args.Result.Read(bytesInStream, 0, (int)bytesInStream.Length);
fs.Write(bytesInStream, 0, bytesInStream.Length);
fs.Flush();
}
}
});
But I would read the complete article to fully understand what happens. Hope this helps!

Categories