Hi,
I'm trying to upload a file to a "File" typed column of a Dataverse table from a PowerApps Portals app.
Other data (e.g. "Text" columns) except for "File" could be registered successfully with "Portals Web API", but I have never succeed uploading a file.
These are what I've tried:
1. Create a record with Portals Web API:
Post a JSON data to the URL "https://{portal URL}/_api/{table name}" and confirmed that the posted data is successfully registered in the table.
2. Upload a file with Portals Web API to the record created (or updated) in #1:
Use "PATCH" HTTP method as the Dataverse API and send "octet-stream" data to the URL "https://{portal URL}/_api/{table name}("ID of the record")/{"File" typed column}".
The API always returns the HTTP code 500 and I have no idea what is going on (the error message is completely useless).
The code of the web page is as in below:
(I've made a blank page and added this code to the content area. ID of the record will be passed from other web page. If no ID is passed, it means a new record will be created.)
{% assign recordId = request.params["id"] %}
{% if recordId == empty or recordId == null %}
{% assign isNew = true %}
{% assign record = null %}
{% else %}
{% assign isNew = false %}
{% assign record = entities['foobar_mytable'][recordId] %}
{% endif %}
<div class="row sectionBlockLayout" style="display: flex; flex-wrap: wrap; padding: 8px; margin: 0px; text-align: left; min-height: 100px;">
<div class="container" style="display: flex; flex-wrap: wrap;">
<div class="col-md-12 columnBlockLayout" style="display: flex; flex-direction: column;">
<div>
<form id="recordDetails">
<div>
<label>Name</label>
{% if record == null %}
<input name="foobar_name" type="text" />
{% else %}
<input name="foobar_name" type="text" value="{{record.foobar_name}}" />
{% endif %}
</div>
<div>
<label>Date</label>
{% if record == null %}
<input name="foobar_date" type="text" />
{% else %}
<input name="foobar_date" type="text" value="{{record.foobar_date | date_to_iso8601}}" />
{% endif %}
</div>
</form>
</div>
<div>
<label>Attachment</label>
{% unless record == null %}
<label>[{{record.foobar_attachment_name}}]</label>
{% endunless %}
<input id="attachment" name="foobar_attachment" type="file" />
</div>
<div>
<input id="submitbutton" type="button" value="Register" onclick="javascript: registerData();" />
{% unless record == null %}
<input id="deletebutton" type="button" value="Delete" onclick="javascript: deleteData();" />
{% endunless %}
<input id="cancelbutton" type="button" value="Cancel" onclick="javascript: cancel();" />
</div>
</div>
</div>
</div>
{% if isNew %}
{% assign registrationUrl = "/_api/foobar_mytables" %}
{% assign methodType = "post" %}
{% else %}
{% assign registrationUrl = "/_api/foobar_mytables(" | append: {{recordId}} | append: ")" %}
{% assign methodType = "patch" %}
{% endif %}
<script type="text/javascript">
(function(webapi, $){
function safeAjax(ajaxOptions) {
var deferredAjax = $.Deferred();
shell.getTokenDeferred().done(function (token) {
// add headers for AJAX
if (!ajaxOptions.headers) {
$.extend(ajaxOptions, {
headers: {
"__RequestVerificationToken": token
}
});
} else {
ajaxOptions.headers["__RequestVerificationToken"] = token;
}
$.ajax(ajaxOptions)
.done(function(data, textStatus, jqXHR) {
validateLoginSession(data, textStatus, jqXHR, deferredAjax.resolve);
}).fail(deferredAjax.reject); //AJAX
}).fail(function () {
deferredAjax.rejectWith(this, arguments); // on token failure pass the token AJAX and args
});
return deferredAjax.promise();
}
webapi.safeAjax = safeAjax;
})(window.webapi = window.webapi || {}, jQuery)
function registerData() {
var json = {};
var serialized = $("#recordDetails").serializeArray();
$.each(serialized, function() {
if (json[this.name] !== undefined) {
if (!json[this.name].push) {
json[this.name] = [o[this.name]];
}
json[this.name].push(this.value || '');
} else {
json[this.name] = this.value || '';
}
});
webapi.safeAjax({
url: "{{registrationUrl}}",
type: "{{methodType}}",
dataType: "json",
contentType: "application/json",
scriptCharset: "utf-8",
data: JSON.stringify(json),
success: function(data, status, xhr) {
if ($("#attachment").prop('files').length) {
// Upload the file after the record is created (or updated).
var newRecordId = xhr.getResponseHeader("entityid");
var newRecordUrl = "/_api/foobar_mytables(" + newRecordId + ")";
var file = $("#attachment").prop('files')[0];
var reader = new FileReader();
reader.onload = function(e) {
var bodyContents = e.target.result;
var buffer = new Uint8Array(bodyContents);
webapi.safeAjax({
url: newRecordUrl + "/foobar_attachment?x-ms-file-name=" + file.name,
type: "patch",
contentType: "application/octet-stream",
processData: false,
data: buffer,
success: function(data, status, xhr) {
alert("The file is successfully uploaded.");
},
error: function(request, status, thrown) {
alert("An error occured.");
}
});
};
reader.readAsArrayBuffer(file);
} else {
alert("Successfully registered the data.");
}
},
error: function(request, status, thrown) {
alert("An error occured.");
}
});
}
function deleteData() {
webapi.safeAjax({
url: "/_api/foobar_mytables({{recordId}})",
type: "delete",
dataType: "json",
contentType: "application/json",
success: function(data, dataType) {
alert("The data has been deleted.");
window.location.href = "/list-sample-page/";
},
error: function(request, status, thrown) {
alert("An error occured.");
}
});
}
function cancel() {
window.location.href = "/list-sample-page/";
}
</script>
If there is no way to upload file with Portals Web API, I can try using Dataverse API but I don't want to write an authentication code (I guess this is the reason why the Portals Web API exists).
I hope I have made some mistake in the code and someone can find it soon.
Thanks in advance!!