Put request to upload zip file to Azureblob. Response as created but No file in blob - rest

I’m trying to upload zip using put request to azure url.
as a result of PUT request i’m getting 201 (created) as result of request.
Snaplogic Response
Here is the details i’m using to upload a file
Blob Url: https://symphnytstcjgrk509.blob.core.windows.net/dmf/GHD%20Forecast%20Interface%20BY.xml?sv=2014-02-14&sr=b&sig=XXXst=2022-11-30T12%3A59%3A44Z&se=2022-11-30T13%3A34%3A44Z&sp=rw
Content-Type : application/zip
Upload transfer request type: Calculate content length
x-ms-blob-type: BlockBlob
The same is getting successfully executed from Post man and the file is uploaded
Do you know what's happening here?

I have uploaded the zipfile using code and able to fetch the file using postman and also using urls.
Create a storage in Azure
Create a container
Code Snippet:
string connection_String = Environment.GetEnvironmentVariable("AzureWebStorage");
string container_Name = Environment.GetEnvironmentVariable("ContainerName");
var file = req.Form.Files["File"];
var filecontent = file.OpenReadStream();
var blobClient = new BlobContainerClient(connection_String, container_Name);
var blob = blobClient.GetBlobClient(file.FileName);
byte[] byteArray = Encoding.UTF8.GetBytes(filecontent.ToString());
using (Stream myblob = new MemoryStream(byteArray))
{
await blob.UploadAsync(myblob);
}
return new OkObjectResult("file uploaded successfylly");
Zip File Uploaded
And also, able to upload and download using URLs.

Related

Using Oauth 2.0 Token to Upload File to Azure Blob Storage

I want to upload (and eventually, download) a file to Azure Blob Storage. I am not allowed to use the Storage SDK, and can only use preloaded libraries (aka requests, json, etc).
So far, I am able to get the token using this method. Once that is done, I build another requests with the required headers. However, I keep getting a 401 Error.
Code to get Token:
# Set the request url
url = f'https://login.microsoftonline.com/{tenant}/oauth2/token'
# Set the request headers
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
resource = 'https://management.azure.com/'
# Set the request body
body = {
'grant_type': 'client_credentials',
'client_id': client_id,
'client_secret': client_secret,
'resource': resource
}
# Make the POST request to the authentication endpoint
response = requests.post(url, headers=headers, data=body)
# Parse the JSON response
response_json = json.loads(response.text)
# Save to variable
oauth_token = response_json['access_token']
Code works, and return a token. Also, to clarify, I am able to upload a file using the SDK library (which means the app registration and permissions are fine), but not manually. PUT request to Azure Blob Storage is as follows:
# Code to upload file to blob storage
# Set the request url
endpoint = f'https://{storage_account_name}.blob.core.windows.net/{container_name}/{blob_name}'
# Open the file to be uploaded
with open(blob_name, "rb") as f:
# Get file size
file_size = str(len(f.read()))
# Get date
now = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
# Move the pointer back to the beginning of the file
f.seek(0)
# Set the headers for the request
headers = {
"Authorization": f"Bearer {oauth_token}",
"x-ms-version":"2020-04-08",
"Content-Length": file_size,
"x-ms-blob-type": "BlockBlob",
"Date": now
}
# Send the PUT request to upload the file
response = requests.put(endpoint, headers=headers, data=f)
response.status_code
Response Status is 401.
Any help is appreciated.
I've tried filling in more than the required header fields. I've deleted and recreated the app registration. Still unable to access the resource.
For those that might be wondering, I should have specified the resource variable as https://<storage_account_name>.blob.core.windows.net. Code now works.

Azure Media Services - Download Transient Error

I have a lot of audios in my database whose URLs are like:
https://mystorage.blob.core.windows.net/mycontainer/uploaded%2F735fe9dc-e568-4920-a3ed-67230ce01991%2F5998d1f8-1795-4776-a19c-f1bc4a0d4786%2F2020-08-13T13%3A09%3A13.0996703Z?sv=2020-02-10&se=2022-01-05T16%3A58%3A50Z&sr=b&sp=r&sig=hQBPyOE92%2F67MqU%2Fe5V2NsqGzgPxogVeXQT%2BOlvbayw%3D
I am using these URLs as my JobInput, and submitting a encoding job, because I want to migrate the audios distribution to a streaming approach.
However, every time I use this kind of URL, it fails with DownloadTransientError, and a message something like while trying to download the input files, the files were not acessible.
If I manually upload a file to the blob storage with a simpler URL (https://mystorage.blob.core.windows.net/mycontainer/my-audio.wav), and use it as the JobInput, it works seamlessly. I suspect it has something to do with the special characters on the bigger URL, but I am not sure. What could be the problem?
Here is the part of the code that submits the job:
var jobInput = new JobInputHttp(new[]
{
audio.AudioUrl.ToString()
});
JobOutput[] jobOutput =
{
new JobOutputAsset(outputAssetName),
};
var job = await client.Jobs.CreateAsync(
resourceGroupName: _azureMediaServicesSettings.ResourceGroup,
accountName: _azureMediaServicesSettings.AccountName,
transformName: TransformName,
jobName: jobName,
new Job
{
Input = jobInput,
Outputs = jobOutput
});
You need to include the file name in the URL you're providing. I'll use your URL as an example, but unescape it as well so that it is more clear. The URL should be something like https://mystorage.blob.core.windows.net/mycontainer/uploaded/735fe9dc-e568-4920-a3ed-67230ce01991/5998d1f8-1795-4776-a19c-f1bc4a0d4786/2020-08-13T13:09:13.0996703Z/my-audio.wav?sv=2020-02-10&se=2022-01-05T16:58:50Z&sr=b&sp=r&sig=hQBPyOE92/67MqU/e5V2NsqGzgPxogVeXQT+Olvbayw=
Just include the actual blob name of the input video or audio file with the associated file extension.

Displaying Images of File Service from Azure in external system + REST API

I have created a method using GETFILE() service of azure. Reference: https://learn.microsoft.com/en-us/rest/api/storageservices/get-file
public void getImage(){
string storageKey = 'xxxxStorageKeyxxx';
string storageName = '<storageName>';
Datetime dt = Datetime.now();
string formattedDate = dt.formatGMT('EEE, dd MMM yyyy HH:mm:ss')+ ' GMT';
string CanonicalizedHeaders = 'x-ms-date:'+formattedDate+'\nx-ms-version:2016-05-31';
string CanonicalizedResource = '/' + storageName + '/<shareName>/<dirName>/<File Name>\ntimeout:20';
string StringToSign = 'GET\n\n\n\n\napplication/octet-stream\n\n\n\n\n\n\n' + CanonicalizedHeaders+'\n'+CanonicalizedResource;
Blob temp = EncodingUtil.base64Decode(storageKey);
Blob hmac = Crypto.generateMac('HmacSHA256',Blob.valueOf(StringToSign),temp ); //StringToSign
system.debug('oo-'+EncodingUtil.base64Encode(hmac));
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setHeader('x-ms-version','2016-05-31' );
req.setHeader('x-ms-date', formattedDate);
req.setHeader('content-type','application/octet-stream');
string signature = EncodingUtil.base64Encode(hmac);
string authHeader = 'SharedKey <storageName>'+':'+signature;
req.setHeader('Authorization',authHeader);
req.setEndpoint('https://<storageName>.file.core.windows.net/<shareName>/<dirName>/<file Name>?timeout=20');
Http http = new Http();
HTTPResponse res;
res = http.send(req);
}
The above was working fine and giving the 200 as response code. But, my main goal is to display/download the respective image which i retrieved through REST API. How can i achieve that?
So a few things before I answer your question:
File storage is not really suitable for what you're trying to accomplish (it's possible though).
You should look at Blob storage for this as blob storage is more suitable for this kind of scenario.
Assuming you go with Blob storage, there are a few things you could do:
If the blob container (equivalent to a share in file storage) has an ACL is Blob or Container (i.e. blobs in a container are publicly available), you could simply return the blob's URL (Same is your request URL in code above) in your response and then create a link in your application with href set to this URL.
If the blob container has an ACL as Private (i.e. blobs are not publicly available), you would need to create a Shared Access Signature (SAS) token on that blob with at least Read permission and then create a SAS URL. A SAS URL is simply blob URL + SAS token and return this SAS URL in your response and then create a link in your application with href set to this URL.
Since an Azure File Share is always private, if you were to use Azure File service to serve a file, you would do the same thing as 2nd option I listed above. You will create a SAS token on the file with at least Read permission and then return the SAS URL in the response and then create a link in your application with href set to this URL.
To read about Shared Access Signature, you may find this link helpful: https://learn.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1.
To create a Shared Access Signature using REST API, you may find this link helpful: https://learn.microsoft.com/en-us/rest/api/storageservices/Constructing-a-Service-SAS?redirectedfrom=MSDN

Upload and Name a File Using Google Drive REST API v3 and Angular 2

I'm creating a Google Drive service using the Drive REST Api v3 in Angular 2. Most of the functionality is in place: view file, download, create etc.. but I cannot find how to name a file (either when creating a file or updating).
I'm using the following docs pages: create and update. They say the file name should be part of the request body. The relevant code from my Google Drive service is bellow.
createFile(name :string, content :string) :Promise<Object> {
let headers = new Headers({
'Content-Type': 'text/markdown',
'Authorization': 'Bearer ' + this.token,
'name': name //TODO name not working!
});
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http
.post('https://www.googleapis.com/upload/drive/v3/files' + '?uploadType=multipart', content, options)
.toPromise();
}
updateFile(id :string, content :string, name :string) :Promise<Object> {
let headers = new Headers({
'Content-Type': 'text/markdown',
'Authorization': 'Bearer ' + this.token,
'id': id,
'name': name //TODO name not working!
}); //generate headers
let options = new RequestOptions({ headers: headers }); // Create a request option
return this.http
.patch('https://www.googleapis.com/upload/drive/v3/files/' + id + '?uploadType=multipart', content, options)
.toPromise();
}
To summarise files are being created and updated fine (including content) but naming and renaming a file doesn't work at all.
Thanks for any help.
Try placing name in the request body and not in the request header as described in the Files: create:
Request body
In the request body, supply a Files resource with the following properties as the metadata. For more information, see the document on media upload.
To test it, try using API Explorer to help you explore various Google APIs interactively.
Sample Request:
POST https://www.googleapis.com/drive/v3/files?key={YOUR_API_KEY}
{
"name": "My File"
}
Response:
200
{
"kind": "drive#file",
"id": "fileID",
"name": "My File"
}
There is also a related SO post that explain how to insert file to Google Drive through API.
Hope this helps.
I also faced that problem. I think there is 3 solutions:
Use multipart upload https://developers.google.com/drive/v3/web/multipart-upload with different headers for file metadata and actual file. Me myself stuck there, didn't found how to add boundaries to separate request headers in Angular 2+
Upload file in two requests. First to create empty file with metadata (response will provide id of the file) and second to actually "update" the file.
Use resumable upload. First request to "setup metadata" (will not even create empty file) and get "special link" where to send request to upload actual file. And this approach have some other features, like uploading in chunks.https://developers.google.com/drive/v3/web/resumable-upload
Here is the link to another Question with implementation of resumable upload in Angular 2 and DRIVE REST API V3
Angular 2+ HTTP POST and GDrive API. Resumable file upload with name
I hope it might be useful.
You are trying to set the name using an http header. This is wrong. I can't begin to understand how you thought that was the way to do it, so you need to go back and reread the Drive API documentation.
In short, the name: "name" should be a JSON object passed in the body of the request, not in an http header.

how to download multiple images using restful webservice

Please let me know How can I download multiple images using Restful webservice? I have a requirement to export multiple images from restful webservice.
I am able to send a single file using below code.
final String FILE_PATH = "D:\\DSC_0493.jpg";
File file = new File(FILE_PATH);
Response.ResponseBuilder response1 = Response.ok((Object) file);
response1.header("Content-Disposition",
"attachment; filename=image_from_server.png");