텍스트가 아닌 파일을 REST API를 통해 SharePoint App에 업로드 할 수 없습니다.
-
10-12-2019 - |
문제
다음 REST 코드를 사용하여 파일을 SharePoint 2013 목록 항목에 첨부 파일로 추가합니다.
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<SharePoint:ScriptLink language="javascript" name="~site/Scripts/js/jquery-1.8.2.js" OnDemand="false" runat="server" Localizable="false"/>
<input id="ufile" type="file" ></input>
<script type="text/javascript">
$(document).ready(
doFunc()
);
function doFunc() {
var control = document.getElementById("ufile");
control.addEventListener("change", doAttach, false);
}
var fileName;
function doAttach(event) {
var files = event.srcElement.files;
if (!window.FileReader) {
alert("The FileSystem APIs are not fully supported in this browser.");
return false;
}
if (files.length > 0) {
var file = files[0];
fileName = file.name;
var reader = new FileReader();
reader.onload = onLoad;
reader.onerror = function(event) {
console.error("File reading error " + event.target.error.code);
};
reader.readAsDataURL(file);
}//
return false;
}
function onLoad(event) {
var contents = event.target.result;
$.ajax({
url: "/Test1/_api/web/lists/GetByTitle('List1')/items(1)/AttachmentFiles/add(FileName='" + fileName + "')",
type: "POST",
contentType: "application/octet-stream;odata=verbose",
data: contents,
headers: {
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function (data)
{
alert("success");
},
error: function (data)
{
alert('error' + data.status + ':' + data.statusText + '\n' + data.responseText);
}
});
}
</script>
</asp:Content>
.
파일이 업로드되지만 "잘못된"데이터가 포함됩니다.
예를 들어 JPEG 파일은 다음과 같이 시작됩니다. 데이터 : Image / JPEG; Base64, / 9j / 4aaqskzjrgabayabgaad /....................................p>
SharePoint 2013 REST API가 텍스트가 아닌 파일을 올바르게 업로드 할 수 있는지 여부를 알고 있습니까?
해결책
I was able to add a file with SP.RequestExecutor
<%-- _lcid="1033" _version="15.0.4128" _dal="1" --%>
<%-- _LocalBinding --%>
<%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=15.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<SharePoint:ScriptLink language="javascript" name="~site/Scripts/js/jquery-1.8.2.js" OnDemand="false" runat="server" Localizable="false"/>
<input id="ufile" type="file" ></input>
<script type="text/javascript">
$(document).ready( dofunc() );
function dofunc() {
var control = document.getElementById("ufile");
control.addEventListener("change", fdocattach, false);
}
var file;
var contents;
function fdocattach(event) {
var i = 0,
files = event.srcElement.files,
len = files.length;
for (; i < len; i++) {
console.log("Filename: " + files[i].name);
console.log("Type: " + files[i].type);
console.log("Size: " + files[i].size + " bytes");
}
if (!window.FileReader) {
alert("The FileSystem APIs are not fully supported in this browser.");
return false;
}
if (files.length > 0) {
file = files[0];
fileName = file.name;
var reader = new FileReader();
reader.onload = fonload;
reader.onerror = function(event) {
console.error("File reading error " + event.target.error.code);
};
reader.readAsArrayBuffer(file);
}
return false;
}
function _arrayBufferToBase64(buffer) {
var binary = ''
var bytes = new Uint8Array(buffer)
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i])
}
return binary;
}
function fonload(event) {
contents = event.target.result;
$.getScript("https://addinexpress966.sharepoint.com/Test1/_layouts/15/SP.RequestExecutor.js", fonload2);
}
function fonload2() {
var contents2 = _arrayBufferToBase64(contents);
var createitem = new SP.RequestExecutor("https://addinexpress966.sharepoint.com/Test1");
createitem.executeAsync({
url: "https://addinexpress966.sharepoint.com/Test1/_api/web/lists/GetByTitle('List1')/items(1)/AttachmentFiles/add(FileName='" + file.name + "')",
method: "POST",
binaryStringRequestBody: true,
body: contents2,
success: fsucc,
error: ferr,
state: "Update"
});
function fsucc(data)
{
alert('success');
}
function ferr(data)
{
alert('error\n\n' + data.statusText + "\n\n" + data.responseText);
}
}
</script>
</asp:Content>
다른 팁
After reading up and a lot of fiddling i came up with setting the data attribute to the file and processData to false. This worked great, except for dropfile not supporting readAsArrayBuffer.
So i used the above convertDataURIToBinary function. Now i have this and it works great. Remarks: files.data is added on the load event and i had to turn async of when attaching multiple files to a listitem.
jQuery.ajax({
url: listUrl + "/items(" + id + ")/AttachmentFiles/add(FileName='" + file.name + "')",
type: "POST",
async: false,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
},
data: convertDataURIToBinary(file.data),
success: function(e) { _.log(_.logType.verbose, "File uploaded: " + e); },
error: function(e) { _.log(_.logType.warning, "File not uploaded: " + e); }
});
var convertDataURIToBinary = function(dataURI) {
var base64Marker = ";base64,";
var base64Index = dataURI.indexOf(base64Marker) + base64Marker.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new window.Uint8Array(new window.ArrayBuffer(rawLength));
for (i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
};
var filesDropped = function (e) {
e = e || window.event;
var files = (e.files || e.dataTransfer.files);
jQuery(files).each(function (index, element) {
var fileReader = new FileReader();
fileReader.file = element;
fileReader.onload = fileLoaded;
fileReader.onerror = function () {
_.log(_.logType.warning, "Error reading file: " + this.file.name);
};
fileReader.readAsDataURL(element);
});
return false;
};
var fileLoaded = function (fileOnloadEvent) {
this.file.data = fileOnloadEvent.target.result;
var filename = this.file.name.toLowerCase();
jQuery(vm.files()).each(function (fIndex, fElement) {
if (fElement.name.toLowerCase() === filename)
vm.removeFile(fElement);
});
vm.files.push(this.file);
};
In this blog post, I use a very similar technique to upload a file from a SharePoint 2013 app using JSOM. I believe the key to what you are looking to do is the utility method convertDataURIToBinary, which will strip out the Base64 prefix and store the data in a binary byte array:
// Utility function to remove base64 URL prefix and store base64-encoded string in a Uint8Array
// Courtesy: https://gist.github.com/borismus/1032746
function convertDataURIToBinary(dataURI)
{
var BASE64_MARKER = ';base64,';
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (i = 0; i < rawLength; i++)
{
array[i] = raw.charCodeAt(i);
}
return array;
}
With out file reader.Like safari 5.0. call openpageindialog on link.
function openpageindialog(itemid) {
var url = "/_layouts/Attachfile.aspx?ListId={LISTID}&ItemId=" + ItemID;
var options = {
url: url,
width: 600,
height: 400,
dialogReturnValueCallback: function(result, fileAdded){
if(result == SP.UI.DialogResult.OK){
//update list of files
console.log("done");
}
}
};
SP.UI.ModalDialog.showModalDialog(options);
}