File Uploading in iOS Xamarin - xamarin.ios

I’ve been trying to upload a PDF file from the file system.
Worked good in iOS Simulator whereas not in iOS Devices.
‘UIFileSharingEnabled’ is set ’True’ in info.plist.
Below’s the Code…is there anything that I am missing?
==================
var docPicker = new UIDocumentPickerViewController(allowedUTIs, UIDocumentPickerMode.Open);
docPicker.DidPickDocumentAtUrls += (object sender, UIDocumentPickedAtUrlsEventArgs e) =>
{
var filename = Path.Combine(e.Urls[0].LastPathComponent);
string msg1 = string.Format("Successfully imported file '{0}'", filename);
string msg2 = string.Format("Failed to import file '{0}'", filename);
NSData data = NSData.FromUrl(e.Urls[0]);
if (data != null)
{
byte[] dataBytes = new byte[data.Length];
ViewModel.PDFBytes = dataBytes;
Console.WriteLine(data + "Completed");
var alertController = UIAlertController.Create("import", msg1, UIAlertControllerStyle.Alert);
var okButton = UIAlertAction.Create("OK", UIAlertActionStyle.Default, (obj) =>
{
alertController.DismissViewController(true, null);
});
alertController.AddAction(okButton);
PresentViewController(alertController, true, null);
}
else
{
var alertController = UIAlertController.Create("import", msg2, UIAlertControllerStyle.Alert);
var okButton = UIAlertAction.Create("OK", UIAlertActionStyle.Default, (obj) =>
{
alertController.DismissViewController(true, null);
});
alertController.AddAction(okButton);
PresentViewController(alertController, true, null);
}
};
PresentViewController(docPicker, true, null);

Try changing your first line:
var docPicker = new UIDocumentPickerViewController(allowedUTIs, UIDocumentPickerMode.Open);
to:
var docPicker = new UIDocumentPickerViewController(allowedUTIs, UIDocumentPickerMode.Import);
Check this link for info:
https://learn.microsoft.com/en-us/dotnet/api/uikit.uidocumentpickermode?view=xamarin-ios-sdk-12

Related

Upload audio blob after conversion from wav to mp3

function init() {
var cfg = {};
audio = new Recorder(cfg);
}
function toggle( btn ){ // audio && audio.record();
if(audio instanceof Recorder){
var btnLabel = btn.firstChild.nodeValue;
if( btnLabel === 'Record' ){
audio.record();
}else{
audio.stop();
createPreview( 'recordings' );
audio.clear();
}
btn.firstChild.nodeValue = (btnLabel === 'Record') ? 'Stop' : 'Record';
btn.setAttribute('class', (btn.getAttribute('class') === 'btn btn-primary') ? 'btn btn-danger' : 'btn btn-primary');
} else {
init();
toggle( btn );
}
}
function createPreview( containerId ) {
// audio && audio.exportWAV( function(blob) {
var targetContainer = document.getElementById( containerId );
var timestamp = new Date().getTime();
var filename = 'recording_'+ timestamp;
var div = document.createElement('div');
var linkMP3 = document.createElement('a');
linkMP3.setAttribute('id', 'MP3-'+ timestamp);
var iconMP3 = document.createElement('img');
iconMP3.setAttribute('src', 'images/i-mp3.jpeg');
var linkWAV = document.createElement('a');
linkWAV.setAttribute('id', 'WAV-'+ timestamp);
var iconWAV = document.createElement('img');
iconWAV.setAttribute('src', 'images/i-wav.jpeg');
var player = document.createElement('audio');
player.setAttribute('id', 'PLAYER-'+ timestamp);
player.controls = true;
div.appendChild(player);
div.appendChild(linkWAV);
div.appendChild(linkMP3);
targetContainer.appendChild(div);
audio.export( function( mediaObj ) {
if( mediaObj.blob.type == 'audio/mp3' ){
var url = mediaObj.url;
targetLink = document.getElementById( 'MP3-'+ timestamp );
targetLink.href = url;
targetLink.download = filename +'.mp3';
targetLink.innerHTML = targetLink.download;
saveAudio( url, filename );
} else { // 'audio/wav'
var url = URL.createObjectURL( mediaObj.blob );
targetPlayer = document.getElementById( 'PLAYER-'+ timestamp );
targetLink = document.getElementById( 'WAV-'+ timestamp );
targetPlayer.src = url;
targetLink.href = url;
targetLink.download = filename +'.wav';
targetLink.innerHTML = targetLink.download;
}
});
}
function saveAudio( url, filename ){
var firebaseUrl = 'your_firebase_url';
if(firebaseUrl !== 'your_firebase_url'){
console.info('>> saving audio: url');
console.log( url );
ref = new Firebase( firebaseUrl );
ref.set({
filetype: 'audio/mp3',
base64Str: url,
filename: filename +'.mp3'
});
}else{
console.warn('Audio not saved to firebase because firebaseUrl is undefined.');
}
}
I need to record audio in the browser (short clips, spoken voice, mono) and upload it in mp3 format. This by Chris Geirman has almost everything that I need, except that instead of using firebase, I'd like to use jquery to upload audio blobs to a folder on my server. I'm fairly new to all of this, but I'm guessing that I need to replace the saveAudio() function with my own uploadAudio() jquery(?) function (something like this), which will link to a script in /upload.php. So far so good (?), but I can't figure out from Chris's script exactly what it is that I should be uploading / passing to /upload.php. I'm planning to implement the script here.
OK just in case it helps anyone I managed to get it working using this from Soumen Basak.
function uploadAudio( blob ) {
var reader = new FileReader();
reader.onload = function(event){
var fd = {};
fd["fname"] = "test.wav";
fd["data"] = event.target.result;
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
dataType: 'text'
}).done(function(data) {
console.log(data);
});
};
reader.readAsDataURL(blob);
}
Replace test.wav with whatever applies - in my case BlahBlah.mp3. Then to reference the blob from Chris Geirman's script, change uploadAudio( blob ); to uploadAudio( mediaObj.blob );.
Be aware that with this set up on localhost, 2 mins of audio took 1'40" to convert from wav to mp3 and move to the uploads directory. Next job, create progress bars, etc!
Upload.php (Thanks again Soumen Basak):
<?
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
$filename = $_POST['fname'];
echo $filename;
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

Does Azure blockBlobURL.download() have a limit to file size?

I'm using Azure's blockBlobURL.download() to download an image but am only receiving the top portion of the image. Is there a limit to how much I can download from Azure blob to a readable stream? The content length is 172628 and there exists a property highWaterMark: 16384. Are these to related?
async function compareToBaseline(imageData, blobName, metadata){
const baselineBlobName = "MacOSX10.12/chrome/initial"
const containerURL = ContainerURL.fromServiceURL(serviceURL, "baselines")
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, baselineBlobName );
let baseLineImage = await blockBlobURL.download(aborter, 0)
baseLineImage = baseLineImage.originalResponse.readableStreamBody.read()
console.log(baseLineImage.length);
baseLineImage = new Buffer(baseLineImage, 'base64');
await fs.writeFile('./newest.png', baseLineImage, 'binary', function(err){
console.log('written');
})
}
The result is only the top portion of an image.
There's a 4-MB limit for each call to the Azure Storage service. If your file is larger than 4 MB, you must break it in chunks. For more information, see Azure Storage scalability and performance targets.
Here is sample c# code to download very large files in 1MB chunks. it's performance oriented too.
private static void DownloadLargeFile()
{
string connectionString = "connString"; //ConfigurationSettings.AppSettings["StorageConnectionString"]; //blob connection string
#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
string sourceContainerName = "quickstartblob"; //ConfigurationSettings.AppSettings["sourcecontainerName"]; //source blob container name
#pragma warning restore CS0618 // Type or member is obsolete
string sourceBlobFileName = "QuickStart1.txt"; //source blob name
CloudStorageAccount account = CloudStorageAccount.Parse(connectionString);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(sourceContainerName);
var file = sourceBlobFileName;
var blob = container.GetBlockBlobReference(file);
//First fetch the size of the blob. We use this to create an empty file with size = blob's size
blob.FetchAttributes();
var blobSize = blob.Properties.Length;
long blockSize = (1 * 1024 * 1024);//1 MB chunk;
blockSize = Math.Min(blobSize, blockSize);
//Create an empty file of blob size
using (FileStream fs = new FileStream(file, FileMode.Create))//Create empty file.
{
fs.SetLength(blobSize);//Set its size
}
var blobRequestOptions = new BlobRequestOptions
{
RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(5), 3),
MaximumExecutionTime = TimeSpan.FromMinutes(60),
ServerTimeout = TimeSpan.FromMinutes(60)
};
long currentPointer = 0;
long bytesRemaining = blobSize;
do
{
var bytesToFetch = Math.Min(blockSize, bytesRemaining);
using (MemoryStream ms = new MemoryStream())
{
//Download range (by default 1 MB)
blob.DownloadRangeToStream(ms, currentPointer, bytesToFetch, null, blobRequestOptions);
ms.Position = 0;
var contents = ms.ToArray();
using (var fs = new FileStream(file, FileMode.Open))//Open that file
{
fs.Position = currentPointer;//Move the cursor to the end of file.
fs.Write(contents, 0, contents.Length);//Write the contents to the end of file.
}
currentPointer += contents.Length;//Update pointer
bytesRemaining -= contents.Length;//Update bytes to fetch
}
}
while (bytesRemaining > 0);
}
Something like below in node js
var azure = require('azure-storage');
var fs = require('fs');
module.exports = function (context, input) {
context.done();
var accessKey = 'myaccesskey';
var storageAccount = 'mystorageaccount';
var containerName = 'mycontainer';
var blobService = azure.createBlobService(storageAccount, accessKey);
var recordName = "a_large_movie.mov";
var blobName = "standard/mov/" + recordName;
var blobSize;
var chunkSize = (1024 * 512) * 8; // I'm experimenting with this variable
var startPos = 0;
var fullPath = "D:/home/site/wwwroot/myAzureFunction/input/";
var blobProperties = blobService.getBlobProperties(containerName, blobName, null, function (error, blob) {
if (error) {
throw error;
}
else {
blobSize = blob.contentLength;
context.log('Registered length: ' + blobSize);
fullPath = fullPath + recordName;
console.log(fullPath);
doDownload();
}
}
);
function doDownload() {
var stream = fs.createWriteStream(fullPath, {flags: 'a'});
var endPos = startPos + chunkSize;
if (endPos > blobSize) {
endPos = blobSize;
context.log('Reached end of file endPos: ' + endPos);
}
context.log("Downloading " + (endPos - startPos) + " bytes starting from " + startPos + " marker.");
blobService.getBlobToStream(
containerName,
blobName,
stream,
{
"rangeStart": startPos,
"rangeEnd": endPos-1
},
function(error) {
if (error) {
throw error;
}
else if (!error) {
startPos = endPos;
if (startPos <= blobSize - 1) {
doDownload();
}
}
}
);
}
};
Hope it helps.
blockBlobURL.download() doesn't have a limit to file size. But read() returns null doesn't mean no more data in the stream. You need to follow Node.js practices to get all data by listening to data or readable event.
For example, the data event posted by Peter Pan. Or the readable event posted by Node.js official documents:
readable.on('readable', () => {
let chunk;
while (null !== (chunk = readable.read())) {
console.log(`Received ${chunk.length} bytes of data.`);
}
});
Please always call read() inside readable event callback.
It seems that this issue was similar with your other thread Unable to read readableStreamBody from downloaded blob.
Here is my function to help saving the baseLineImage.readableStreamBody to a file, as below.
async function streamToFs(filename, readableStream) {
const ws = fs.createWriteStream(filename);
readableStream.on("data", data => {
ws.write(data);
}).on("end", () => {
console.log('written');
});
}
And change your code as below.
async function compareToBaseline(imageData, blobName, metadata){
const baselineBlobName = "MacOSX10.12/chrome/initial"
const containerURL = ContainerURL.fromServiceURL(serviceURL, "baselines");
const blockBlobURL = BlockBlobURL.fromContainerURL(containerURL, baselineBlobName );
let baseLineImage = await blockBlobURL.download(aborter, 0);
await streamToFs('./newest.png', baseLineImage.readableStreamBody);
}
It works. Hope it helps.

nodejs base64 to blob conversion

Iam capturing webcam screenshot in reactjs(react-webcam). Screenshot is in the form of base64 encoded string. I am sending the base 64string to nodejs and I want to convert base64 String to .jpeg file, So that I can save in Azure Blob Storage.
Is there any method to convert base64 string to .jpeg file.
You can convert your Base64 string to Buffer and then try storing it to azure.
var base64String = "....."; // your base64 string
var bufferValue = Buffer.from(base64String,"base64");
I used this and it worked.
below is server side code(NodeJS)
var contentType = 'image/jpeg';
let base64String=req.body.img;
let base64Image = base64String.split(';base64,').pop();
let date=Date.now();
fs.writeFile(`./uploads/${date}.jpeg`, base64Image, {encoding: 'base64'}, function(err) {
console.log('File created');
sourceFilePath= path.resolve(`./uploads/${date}.jpeg`);
blobName=path.basename(sourceFilePath, path.extname(sourceFilePath));
//console.log(sourceFilePath);
blobService.createBlockBlobFromLocalFile(containerName, blobName, sourceFilePath, err => {
if (err) {
console.log(err);
}
else {
//resolve({ message: `Upload of '${blobName}' complete` });
console.log("UPLOADED")
}
});
Try this:
based-blob
(async function() {
const b = require('based-blob');
const base64String = 'some base64 data...';
const blob = b.toBlob(base64String);
const b64s = await b.toBase64(blob);
console.log(b64s == base64String); // true
})();
Hi i use this function
public b64toBlob = (b64Data: string = '', sliceSize?: number) => {
sliceSize = sliceSize || 512;
if ( b64Data !== null) {
let block = b64Data.split(';');
let dataType = block[0].split(':')[1];
let realData = block[1].split(',')[1];
let filename = this.makeid() + '.' + dataType.split('/')[1];
let byteCharacters = atob(realData);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
let blob = new Blob(byteArrays, {type: dataType});
return blob ;
} else {
return '';
}
}

Plupload Error -200 HTTP Error

I am trying to move the uploading on a remote server. After I choose a file with the code below and click upload the file IS uploaded, but an error returns saying code: "-200" message: "HTTP Error"
var uploader = new plupload.Uploader(
{
runtimes : 'html4, html5, flash, silverlight',
browse_button : 'bt_browse',
container: document.getElementById('container'),
url : 'http://remote.com/upload.php',
silverlight_xap_url : 'js/Moxie.xap',
chunks_size: '20mb',
max_retries: 3,
filters : {
max_file_size : '100mb'
},
multi_selection : true,
init: {
PostInit: function() {
document.getElementById('filelist').innerHTML = '';
document.getElementById('bt_uploadfiles').onclick = function() {
uploader.start();
return false;
};
},
FilesAdded: function(up, files) {
plupload.each(files, function(file) {
//build list
}},
UploadProgress: function(up, file) {
$("#progressBar"+file.id).val(Math.round(file.percent));
if(Math.round(file.percent)==100){
$("#progressBar"+file.id).hide();
$("#deleteFile" + file.id).hide();
}
},
FileUploaded: function(up, file, info) {
if(file!=undefined) {
var json = $.parseJSON(info.response);
if(json.error == undefined)
moveFile(json.result, file.name, file.id);
}
},
UploadComplete: function(){
},
Error: function(up, err) {
}
}
});
What can I do to escape this error and continue? In my case FileUploaded and UploadProgress are not hit at all - after I hit upload I directly moved to Error function. This is really weird for me since after that I check the folder where it is supposed to be and the file is there.
Any help will be much appreciated.
I came across the same error when I was using PlUpload in an MVC5 application. The problem was that the REST method could not be found. PlUpload using a multipart for data. The code below shows how this could be implemented in a WebAPI
public class UploadFilesController : ApiController
{
[HttpPost]
[Route("UploadFiles")]
public async Task<HttpResponseMessage> PostFormData()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
var TestId = provider.FormData.Get("TestId");
var chunk = provider.FormData.Get("chunk");
var chunks = provider.FormData.Get("chunks");
var fileName = provider.FormData.Get("name");
int chunkId = Convert.ToInt32(chunk);
int totalChunks = Convert.ToInt32(chunks);
Boolean isLastChunch = chunkId == totalChunks - 1;
foreach (MultipartFileData file in provider.FileData)
{
//Console.WriteLine(file.Headers.ContentDisposition.FileName);
//Console.WriteLine("Server file path: " + file.LocalFileName);
string FileDestination = Path.GetDirectoryName(file.LocalFileName) + #"\" + fileName;
using (FileStream fileUpload = new FileStream(file.LocalFileName, FileMode.Open))
{
using (var fs = new FileStream(FileDestination, chunkId == 0 ? FileMode.Create : FileMode.Append))
{
var buffer = new byte[fileUpload.Length];
fileUpload.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, buffer.Length);
}
}
File.Delete(file.LocalFileName);
}
if (isLastChunch) {
// Do something with the completed file
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}

Check if Current Users belongs to SP group using javascript Client Side Object Model

I havent found a specific example of how to get the current user and then check if it belongs to a specific sharepoint group, as I havent found anything I cant provide a code,
help on the right direction is appreciated.
SharePoint 2013 CSOM
Prerequisites: compatible with SharePoint 2013 CSOM API only since
SP.GroupCollection.getByName Method is not available in
SharePoint 2010
How to check if current user belongs to SharePoint group via CSOM (JavaScript):
function IsCurrentUserMemberOfGroup(groupName, OnComplete) {
var currentContext = new SP.ClientContext.get_current();
var currentWeb = currentContext.get_web();
var currentUser = currentContext.get_web().get_currentUser();
currentContext.load(currentUser);
var allGroups = currentWeb.get_siteGroups();
currentContext.load(allGroups);
var group = allGroups.getByName(groupName);
currentContext.load(group);
var groupUsers = group.get_users();
currentContext.load(groupUsers);
currentContext.executeQueryAsync(OnSuccess,OnFailure);
function OnSuccess(sender, args) {
var userInGroup = false;
var groupUserEnumerator = groupUsers.getEnumerator();
while (groupUserEnumerator.moveNext()) {
var groupUser = groupUserEnumerator.get_current();
if (groupUser.get_id() == currentUser.get_id()) {
userInGroup = true;
break;
}
}
OnComplete(userInGroup);
}
function OnFailure(sender, args) {
OnComplete(false);
}
}
Usage
IsCurrentUserMemberOfGroup("Approvers", function (isCurrentUserInGroup) {
if(isCurrentUserInGroup)
{
//...
}
});
SharePoint 2010/2013 CSOM
function isUserMemberOfGroup(userId, groupId, success,error) {
var ctx = SP.ClientContext.get_current();
var allGroups = ctx.get_web().get_siteGroups();
var group = allGroups.getById(groupId);
ctx.load(group,'Users');
ctx.executeQueryAsync(
function(sender, args) {
var userInGroup = findUserById(group.get_users(),userId);
success(userInGroup);
},
error);
var findUserById = function(users,id){
var found = false;
var e = group.get_users().getEnumerator();
while (e.moveNext()) {
var user = e.get_current();
if (user.get_id() == id) {
found = true;
break;
}
}
return found;
};
}
Usage
var currentUserId = _spPageContextInfo.userId;
var groupId = 4;
isUserMemberOfGroup(currentUserId, groupId,
function (isCurrentUserInGroup) {
if(isCurrentUserInGroup)
console.log('Current user is a member of Owners group');
else
console.log('Current user is not a member of Owners group');
},
function(sender,args){
console.log(args.get_message());
});
Here's a quicker way with SharePoint 2013:
function CheckCurrentUserMembership() {
var clientContext = new SP.ClientContext.get_current();
this.currentUser = clientContext.get_web().get_currentUser();
clientContext.load(this.currentUser);
this.userGroups = this.currentUser.get_groups();
clientContext.load(this.userGroups);
clientContext.executeQueryAsync(OnQuerySucceeded);
}
function OnQuerySucceeded() {
var isMember = false;
var groupsEnumerator = this.userGroups.getEnumerator();
while (groupsEnumerator.moveNext()) {
var group= groupsEnumerator.get_current();
if(group.get_title() == "Administrator Group") {
isMember = true;
break;
}
}
OnResult(isMember);
}
function OnQueryFailed() {
OnResult(false);
}
If anyone is interested. This approach can be used when you want to check if a user is a member of a group using the group name.
var currentUserIsMemberOf = function(groupName){
var found = false;
var dfd = $.Deferred(function(){
SP.SOD.executeOrDelayUntilScriptLoaded(function(){
context = new SP.ClientContext.get_current();
allGroups = context.get_web().get_siteGroups();
context.load(allGroups);
context.load(allGroups, 'Include(Users)');
context.executeQueryAsync(
function(){
var groupsEnumerator = allGroups.getEnumerator();
while (groupsEnumerator.moveNext()) {
var group = groupsEnumerator.get_current();
if(group.get_title() == groupName) {
var usersEnumerator = group.get_users().getEnumerator();
while (usersEnumerator.moveNext()) {
var user = usersEnumerator.get_current();
if(user.get_id() == _spPageContextInfo.userId) {
found = true;
break;
}
}
}
}
dfd.resolve(found);
},
function(){
dfd.reject(args.get_message());
}
);
}, 'sp.js');
});
return dfd.promise();
}
You can use like this
currentUserIsMemberOf("Members of Demo").done(function(result){
alert(result)
});
Note this code use Promise, you can reference jQuery use your own custom Deferred object or remove Deferred object.

Resources