Does anyone have some experience with cache-control on Windows azure. I just can't get it to work. I have a JSON file which I want some caching rules on. I have the following code:
var matchContainer = _blobClient.GetContainerReference(match.ClassContainer);
matchContainer.CreateIfNotExists();
matchContainer.SetPermissions(new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
// save the blob into the blob service
string uniqueBlobName = string.Format("matchdata/" + match.KeyPath + ".json").ToLower();
CloudBlockBlob blob = matchContainer.GetBlockBlobReference(uniqueBlobName);
var matchString = match.ToString();
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.AutoFlush = true;
writer.Write(matchString);
stream.Seek(0, SeekOrigin.Begin);
blob.UploadFromStream(stream);
blob.Properties.CacheControl = "max-age=3600, must-revalidate";
blob.SetProperties();
Which is exactly the same as a sample over here
Sample of setting Cache-Control
The header just doesn't get set. Hope you can help.
if you are using fiddle on windows 8.1 preview, I have noticed that it doesn't always hit the cache. I had to use chrome to validate the cache hit for my blog post.
Alex
Related
I have an azure function where I need to fetch an image from an azure blob container and then I send it to an external API. For this I download it to a memorystream and then send it as a stream to the API.
The code I use for this is the following:
var storageConnection = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
var containerName = Environment.GetEnvironmentVariable("BlobContainerName");
var cloudStorageAccount = CloudStorageAccount.Parse(storageConnection);
var blobClient = cloudStorageAccount.CreateCloudBlobClient();
var cloudBlobContainer = blobClient.GetContainerReference(containerName);
var blockBlob = cloudBlobContainer.GetBlockBlobReference(filename);
var memStream = new MemoryStream();
blockBlob.DownloadToStream(memStream);
This works fine with normal images, but somehow doesn't work for items saved as an octet-stream (which occurs when uploading an image via a certain upload page).
Does anyone have any idea why this is and how to fix it?
Thanks in advance!
If anyone else would have this issue, I fixed it very easily:
instead of
var memStream = new MemoryStream();
blockBlob.DownloadToStream(memStream);
I used
var stream = await blockBlob.OpenReadAsync();
I can download a file from the Amazon S3 Storage with below code,
var s3Client = new AmazonS3Client(txt_Accesskey.Text, txt_Secretkey.Text, bucketRegion);
GetObjectRequest request = new GetObjectRequest();
request.BucketName = bucketName;
request.Key = "Sample.txt";
GetObjectResponse response = s3Client.GetObject(request);
response.WriteResponseStreamToFile(#"C:\Desktop\Sample.txt");
But, I want to download these files as Byte Array. Can anyone please give me a solution for this?
Just quickly looking at the docs, you maybe able to do this
using (GetObjectResponse response = client.GetObject(request))
bytes = response.ResponseStream.ToArray();
I am trying to call the Microsoft Cognitive API by passing multiple images as per documentation and using the multipart/form-data, but I am getting an error that says "Unsupported Media Type". I have tried to use both ByteArray and StreamContent.
Api documentation.
private static byte[] GetImageAsByteArray(Stream fileStream)
{
using (var binaryReader = new BinaryReader(fileStream))
{
return binaryReader.ReadBytes((int)fileStream.Length);
}
}
static void Main(string[] args)
{
var uriBase = "https://westus.api.cognitive.microsoft.com/vision/v1.0/recognizeText";
var subscriptionKey = "<subscriptionKey>";
var client = new HttpClient();
var uri = string.Concat(uriBase, "?", "language=en&detectOrientation=true");
var images = new List<Stream>();
var img = Image.FromStream(File.Open("<imageName>", FileMode.Open));
var stream = new MemoryStream();
img.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
images.Add(stream);
using (var content = new MultipartFormDataContent())
{
foreach (var image in images)
{
//content.Add(new StreamContent(stream));
content.Add(new ByteArrayContent(GetImageAsByteArray(image)));
}
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
var response = client.PostAsync(uri, content).Result;
}
}
I am trying to call the Microsoft Cognitive API by passing multiple images as per documentation and using the multipart/form-data, but I am getting an error that says "Unsupported Media Type".
It is not possible to send multiple images, regardless of header.
Please refer to the documentation Step 2, it mentions:
The basic way to perform the Computer Vision API call is by uploading an image directly. This is done by sending a "POST" request with application/octet-stream content type together with the data read from the image.
Example code can be found here
Test environment here.
Notice regardless of header, it is still sending 1 image.
The limits also mention a single image.
I have a web api method that returns an HttpResponseMessage containing a PDF file. The method looks something like this:
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(new FileStream(path, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
When I call this api from client (which is written in angularJS), the Internet Download Manager automatically catches the PDF file and wants to download it. And because I have a security plan for my project, the IDM automatically requests username and password.
Does anyone have an idea about how I'm supposed to programmatically stop IDM from catching the PDF file?
Update: Here's my angularJS code:
$http.post(url, { transactionId: txId }
, {responseType: 'arraybuffer'})
.success(function (response) {
var reader = new FileReader();
var file = new Blob([response.data], {type: 'application/pdf'});
reader.onload = function (e) {
var printElem = angular.element('#printPdfLink');
printElem.attr('target', '_blank');
printElem.attr('href', reader.result);
printElem.attr('ng-click', '');
};
reader.readAsDataURL(file);
})
.error(function (error) {});
Change the mime type to application/octet-stream as a way to work around your problem. Make sure that the file name includes a proper file extension so that it can be recognized by the client system once downloaded.
Another issue is the attachment disposition of the content which typically forces it to save it as a file download. Change it to inline so that the client can consume it without IDM trying to download it as an attachment.
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamContent content new StreamContent(stream);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline");
content.Headers.ContentDisposition.FileName = fileName;
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = content;
return response;
I have try to use HttpResponseMessage.
If I use ContentDisposition is inline then response break the file. If use attachment then IDM can detect it.
At the end of the day, I found Accept-Ranges header can make download without IDM but it not valid in HttpResponseMessage.
You can try out my code below to make download file without IDM:
[HttpGet]
[Route("~/download/{filename}")]
public void Download(string filename)
{
// TODO lookup file path by {filename}
// If you want to have "." in {filename} you need enable in webconfig
string filePath = "<path>"; // your file path here
byte[] fileBytes = File.ReadAllBytes(filePath);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("Accept-Ranges", "bytes");
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("ContentDisposition", "attachment, filename=" + filename);
HttpContext.Current.Response.BinaryWrite(fileBytes);
HttpContext.Current.Response.End();
}
Note: filename parameter serve for download file name so you can config in webconfig if you want to have file extension (disabled by default).
I am using c# to create shared access signatures for new resources (The user should have create privileges to create new resources on my storage account).
The MS documentation is out of date and I can't seem to get it to work using the different blog posts I've gone through.
Right now my code looks like so:
public static string GetBlobSharedAccessSignitureUrl(CloudBlobContainer container,string nameOfBlobToCreateSaSfor)
{
var blob = container.GetBlockBlobReference(nameOfBlobToCreateSaSfor);
var policy = new SharedAccessBlobPolicy
{
SharedAccessExpiryTime = DateTime.Now.AddHours(1),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read
};
container.GetSharedAccessSignature(policy);
string sas = blob.GetSharedAccessSignature(policy);
return blob.Uri.AbsoluteUri + sas;
}
and the returned url (for my local machine) looks like this (what seems to be correct)
http://127.0.0.1:10000/devstoreaccount1/photos/photos_4.jpg?sv=2012-02-12&se=2013-01-20T10%3A13%3A17Z&sr=b&sp=rw&sig=xxx
I started the Azure storage simulator and through fiddler tried to POST to this URL (also tried PUT)
I am getting errors (404 or 400 , depends on different code for this function that I have tried)
Do I need to do something else? (In the old examples I saw them create a resource in that location before hand - which I've tried as well but didn't work either...)
Azure SDK version is 2.0 so the MS blog posts (and other tutorials) before October 2012 are broken (also according to MS dev blog http://blogs.msdn.com/b/windowsazurestorage/archive/2012/10/29/windows-azure-storage-client-library-2-0-breaking-changes-amp-migration-guide.aspx)
any help would be appreciated
If you're posting through Fiddler or through your code, please make sure you add "x-ms-blob-type" request header and set it's value as "BlockBlob". Take a look at this sample code where it tries to upload a file:
FileInfo fInfo = new FileInfo(fileName);//fileName is the full path of the file.
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(blobSaSUrl);
NameValueCollection requestHeaders = new NameValueCollection();
requestHeaders.Add("x-ms-blob-type", "BlockBlob");
req.Method = "PUT";
req.Headers.Add(requestHeaders);
req.ContentLength = fInfo.Length;
byte[] fileContents = new byte[fInfo.Length];
using (FileStream fs = fInfo.OpenRead())
{
fs.Read(fileContents, 0, fileContents.Length);
using (Stream s = req.GetRequestStream())
{
s.Write(fileContents, 0, fileContents.Length);
}
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
{
}
}
Create a SAS token that's valid for one hour.
BlobSasBuilder sasBuilder = new BlobSasBuilder()
{
BlobContainerName = containerName,
BlobName = blobName,
Resource = "b",
StartsOn = DateTimeOffset.UtcNow,
ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
};
Specify read permissions for the SAS.
sasBuilder.SetPermissions(BlobSasPermissions.Read);
Use the key to get the SAS token.
string sasToken = sasBuilder.ToSasQueryParameters(key, accountName).ToString();
Construct the full URI, including the SAS token.
UriBuilder fullUri = new UriBuilder()
{
Scheme = "https",
Host = string.Format("{0}.blob.core.windows.net", accountName),
Path = string.Format("{0}/{1}", containerName, blobName),
Query = sasToken
};