/// <summary> /// Attempts to upload a single file a Tableau Server, and then make it a published workbook /// </summary> /// <param name="localFilePath"></param> /// <returns></returns> private bool AttemptUploadSingleFile_Inner( string localFilePath, string projectId, CredentialManager.Credential dbCredentials) { string uploadSessionId; try { var fileUploader = new UploadFile(_onlineUrls, _onlineSession, localFilePath, _uploadChunkSizeBytes, _uploadChunkDelaySeconds); uploadSessionId = fileUploader.ExecuteRequest(); } catch (Exception exFileUpload) { this.StatusLog.AddError("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message); throw exFileUpload; } this.StatusLog.AddStatus("File chunks upload successful. Next step, make it a published workbook", -10); try { string fileName = Path.GetFileNameWithoutExtension(localFilePath); string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower()); var workbook = FinalizePublish(uploadSessionId, fileName, uploadType, projectId, dbCredentials); StatusLog.AddStatus("Upload content details: " + workbook.ToString(), -10); StatusLog.AddStatus("Success! Uploaded workbook " + Path.GetFileName(localFilePath)); } catch (Exception exPublishFinalize) { this.StatusLog.AddError("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message); LogManualAction_UploadWorkbook(localFilePath); throw exPublishFinalize; } return(true); //Success }
/// <summary> /// Attempts to upload a single file a Tableau Server, and then make it a published workbook /// </summary> /// <param name="localFilePath"></param> /// <returns></returns> private bool AttemptUploadSingleFile_Inner( string localFilePath, string projectId, CredentialManager.Credential dbCredentials, WorkbookPublishSettings publishSettings) { string uploadSessionId; try { var fileUploader = new UploadFile(_onlineUrls, _onlineSession, localFilePath, _uploadChunkSizeBytes, _uploadChunkDelaySeconds); uploadSessionId = fileUploader.ExecuteRequest(); } catch (Exception exFileUpload) { this.StatusLog.AddError("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message); throw exFileUpload; } SiteWorkbook workbook; this.StatusLog.AddStatus("File chunks upload successful. Next step, make it a published workbook", -10); try { string fileName = Path.GetFileNameWithoutExtension(localFilePath); string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower()); workbook = FinalizePublish( uploadSessionId, FileIOHelper.Undo_GenerateWindowsSafeFilename(fileName), //[2016-05-06] If the name has escapted characters, unescape them uploadType, projectId, dbCredentials, publishSettings); StatusLog.AddStatus("Upload content details: " + workbook.ToString(), -10); StatusLog.AddStatus("Success! Uploaded workbook " + Path.GetFileName(localFilePath)); } catch (Exception exPublishFinalize) { this.StatusLog.AddError("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message); LogManualAction_UploadWorkbook(localFilePath); throw exPublishFinalize; } //See if we want to reassign ownership of the workbook if (_attemptOwnershipAssignment) { try { AttemptOwnerReassignment(workbook, publishSettings, _siteUsers); } catch (Exception exOwnershipAssignment) { this.StatusLog.AddError("Unexpected error reassigning ownership of published workbook " + workbook.Name + ", " + exOwnershipAssignment.Message); LogManualAction_ReassignOwnership(workbook.Name); throw exOwnershipAssignment; } } return(true); //Success }
/// <summary> /// Attempts to upload a single file a Tableau Server, and then make it a published data source /// </summary> /// <param name="localFilePath"></param> /// <param name="projectId"></param> /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param> /// <returns></returns> private bool AttemptUploadSingleFile( string localFilePath, string projectId, CredentialManager.Credential dbCredentials, DatasourcePublishSettings publishSettings) { string uploadSessionId; try { var fileUploader = new UploadFile(Urls, Login, localFilePath, HttpClientFactory, UploadChunkSizeBytes, UploadChunkDelaySeconds); uploadSessionId = fileUploader.ExecuteRequest(); } catch (Exception exFileUpload) { Login.Logger.Error("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message); throw exFileUpload; } SiteDatasource dataSource = null; Login.Logger.Information("File chunks upload successful. Next step, make it a published datasource"); try { string fileName = Path.GetFileNameWithoutExtension(localFilePath); string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower()); dataSource = FinalizePublish( uploadSessionId, FileIOHelper.Undo_GenerateWindowsSafeFilename(fileName), //[2016-05-06] If the name has escapted characters, unescape them uploadType, projectId, dbCredentials); UploadeDatasources.Add(dataSource); Login.Logger.Information("Upload content details: " + dataSource.ToString()); Login.Logger.Information("Success! Uploaded datasource " + Path.GetFileName(localFilePath)); } catch (Exception exPublishFinalize) { Login.Logger.Error("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message); throw exPublishFinalize;; } //See if we want to reassign ownership of the datasource if (AttemptOwnershipAssignment) { try { AttemptOwnerReassignment(dataSource, publishSettings, SiteUsers); } catch (Exception exOwnershipAssignment) { Login.Logger.Error("Unexpected error reassigning ownership of published datasource " + dataSource.Name + ", " + exOwnershipAssignment.Message); LogManualAction_ReassignOwnership(dataSource.Name); throw exOwnershipAssignment; } } return(true); //Success }
/// <summary> /// /// </summary> /// <param name="thisFilePath"></param> /// <param name="projectIdForUploads"></param> /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param> /// <param name="publishSettings">Workbook publish settings (e.g. whether to show tabs in vizs)</param> private bool AttemptUploadSingleFile( string thisFilePath, string projectIdForUploads, CredentialManager.Credential dbCredentials, WorkbookPublishSettings publishSettings) { return(AttemptUploadSingleFile_Inner(thisFilePath, projectIdForUploads, dbCredentials, publishSettings)); }
/// <summary> /// After a file has been uploaded in chunks, we need to make a call to COMMIT the file to server as a published Data Source /// </summary> /// <param name="uploadSessionId"></param> /// <param name="publishedContentName"></param> private SiteDatasource FinalizePublish( string uploadSessionId, string publishedContentName, string publishedContentType, string projectId, CredentialManager.Credential dbCredentials) { //See definition: http://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm#REST/rest_api_ref.htm#Publish_Datasource%3FTocPath%3DAPI%2520Reference%7C_____29 var sb = new StringBuilder(); var xmlWriter = XmlWriter.Create(sb, XmlHelper.XmlSettingsForWebRequests); xmlWriter.WriteStartElement("tsRequest"); xmlWriter.WriteStartElement("datasource"); xmlWriter.WriteAttributeString("name", publishedContentName); //If we have an associated database credential, write it out if (dbCredentials != null) { CredentialXmlHelper.WriteCredential( xmlWriter, dbCredentials); } xmlWriter.WriteStartElement("project"); //<project> xmlWriter.WriteAttributeString("id", projectId); xmlWriter.WriteEndElement(); //</project> xmlWriter.WriteEndElement(); // </datasource> //Currently not supporting <connectionCredentials> xmlWriter.WriteEndElement(); // </tsRequest> xmlWriter.Dispose(); var xmlText = sb.ToString(); //Get the XML text out //Generate the MIME message var mimeGenerator = new MimeWriterXml(xmlText); //Create a web request to push the var urlFinalizeUpload = Urls.Url_FinalizeDataSourcePublish(Login, uploadSessionId, publishedContentType); //NOTE: The publish finalization step can take several minutes, because server needs to unpack the uploaded ZIP and file it away. // For this reason, we pass in a long timeout var response = this.CreateAndSendMimeLoggedInRequest(urlFinalizeUpload, HttpMethod.Post, mimeGenerator); var xmlDoc = GetHttpResponseAsXml(response); //Get all the datasource node from the response var xDoc = xmlDoc.ToXDocument(); var dataSourceXml = xDoc.Root.Descendants(XName.Get("datasource", XmlNamespace)).FirstOrDefault(); try { return(new SiteDatasource(dataSourceXml.ToXmlNode(), XmlNamespace)); } catch (Exception parseXml) { Login.Logger.Error("Data source upload, error parsing XML response " + parseXml.Message + "\r\n" + dataSourceXml.ToXmlNode()); return(null); } }
/// <summary> /// After a file has been uploaded in chunks, we need to make a call to COMMIT the file to server as a published Data Source /// </summary> /// <param name="uploadSessionId"></param> /// <param name="publishedContentName"></param> private SiteDatasource FinalizePublish( string uploadSessionId, string publishedContentName, string publishedContentType, string projectId, CredentialManager.Credential dbCredentials) { //See definition: http://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm#REST/rest_api_ref.htm#Publish_Datasource%3FTocPath%3DAPI%2520Reference%7C_____29 var sb = new StringBuilder(); var xmlWriter = XmlWriter.Create(sb, XmlHelper.XmlSettingsForWebRequests); xmlWriter.WriteStartElement("tsRequest"); xmlWriter.WriteStartElement("datasource"); xmlWriter.WriteAttributeString("name", publishedContentName); //If we have an associated database credential, write it out if (dbCredentials != null) { CredentialXmlHelper.WriteCredential( xmlWriter, dbCredentials); } xmlWriter.WriteStartElement("project"); //<project> xmlWriter.WriteAttributeString("id", projectId); xmlWriter.WriteEndElement(); //</project> xmlWriter.WriteEndElement(); // </datasource> //Currently not supporting <connectionCredentials> xmlWriter.WriteEndElement(); // </tsRequest> xmlWriter.Close(); var xmlText = sb.ToString(); //Get the XML text out //Generate the MIME message var mimeGenerator = new MimeWriterXml(xmlText); //Create a web request to push the var urlFinalizeUpload = _onlineUrls.Url_FinalizeDataSourcePublish(_onlineSession, uploadSessionId, publishedContentType); //NOTE: The publish finalization step can take several minutes, because server needs to unpack the uploaded ZIP and file it away. // For this reason, we pass in a long timeout var webRequest = this.CreateAndSendMimeLoggedInRequest(urlFinalizeUpload, "POST", mimeGenerator, TableauServerWebClient.DefaultLongRequestTimeOutMs); var xmlDoc = GetWebReponseLogErrors_AsXmlDoc(webRequest, "finalize datasource publish"); //Get all the datasource node from the response var nsManager = XmlHelper.CreateTableauXmlNamespaceManager("iwsOnline"); var dataSourceXml = xmlDoc.SelectSingleNode("//iwsOnline:datasource", nsManager); try { return(new SiteDatasource(dataSourceXml)); } catch (Exception parseXml) { StatusLog.AddError("Data source upload, error parsing XML response " + parseXml.Message + "\r\n" + dataSourceXml.InnerXml); return(null); } }
/// <summary> /// Makes a copy of the file; remaps the Workbook references to the server, uploads the remapped file /// </summary> /// <param name="thisFilePath"></param> /// <param name="projectIdForUploads"></param> private bool AttemptUploadSingleFile_ReferencesRemapped( string thisFilePath, string projectIdForUploads, CredentialManager.Credential dbCredentials, WorkbookPublishSettings publishSettings) { bool success = false; string filename = Path.GetFileName(thisFilePath); string pathToRemapFile = Path.Combine(_localPathTempWorkspace, filename); File.Copy(thisFilePath, pathToRemapFile, true); //Copy the file string fileType = Path.GetExtension(filename).ToLower(); if (fileType == ".twb") { //Remap the references in the file var twbRemapper = new TwbDataSourceEditor(pathToRemapFile, pathToRemapFile, _onlineUrls, this.StatusLog); twbRemapper.Execute(); success = AttemptUploadSingleFile_Inner(pathToRemapFile, projectIdForUploads, dbCredentials, publishSettings); } else if (fileType == ".twbx") { //Make sure we have a directory to unzip to var pathUnzip = Path.Combine(_localPathTempWorkspace, "unzipped"); if (Directory.Exists(pathUnzip)) { Directory.Delete(pathUnzip, true); } Directory.CreateDirectory(pathUnzip); var twbxRemapper = new TwbxDataSourceEditor(pathToRemapFile, pathUnzip, _onlineUrls, this.StatusLog); string pathTwbxRemappedOutput = twbxRemapper.Execute(); //Upload the remapped file success = AttemptUploadSingleFile_Inner(pathTwbxRemappedOutput, projectIdForUploads, dbCredentials, publishSettings); //Clean-up and delete the whole unzipped directory Directory.Delete(pathUnzip, true); } else { //We should never hit this... bad content this.StatusLog.AddError("Error Workbook upload - Expected Workbook filetype! " + filename); } //Delete the remap file File.Delete(pathToRemapFile); return(success); }
/// <summary> /// /// </summary> /// <param name="thisFilePath"></param> /// <param name="projectIdForUploads"></param> /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param> private bool AttemptUploadSingleFile( string thisFilePath, string projectIdForUploads, CredentialManager.Credential dbCredentials) { //Assume it's a file we should try to upload if (_remapWorkbookReferences) { return(AttemptUploadSingleFile_ReferencesRemapped(thisFilePath, projectIdForUploads, dbCredentials)); } else { return(AttemptUploadSingleFile_Inner(thisFilePath, projectIdForUploads, dbCredentials)); } }
/// <summary> /// Attempts to upload a single file a Tableau Server, and then make it a published data source /// </summary> /// <param name="localFilePath"></param> /// <param name="projectId"></param> /// <param name="dbCredentials">If not NULL, then these are the DB credentials we want to associate with the content we are uploading</param> /// <returns></returns> private bool AttemptUploadSingleFile( string localFilePath, string projectId, CredentialManager.Credential dbCredentials) { string uploadSessionId; try { var fileUploader = new UploadFile(_onlineUrls, _onlineSession, localFilePath, _uploadChunkSizeBytes, _uploadChunkDelaySeconds); uploadSessionId = fileUploader.ExecuteRequest(); } catch (Exception exFileUpload) { this.StatusLog.AddError("Unexpected error attempting to upload file " + localFilePath + ", " + exFileUpload.Message); throw exFileUpload; } this.StatusLog.AddStatus("File chunks upload successful. Next step, make it a published datasource", -10); try { string fileName = Path.GetFileNameWithoutExtension(localFilePath); string uploadType = RemoveFileExtensionDot(Path.GetExtension(localFilePath).ToLower()); var dataSource = FinalizePublish( uploadSessionId, FileIOHelper.Undo_GenerateWindowsSafeFilename(fileName), //[2016-05-06] If the name has escapted characters, unescape them uploadType, projectId, dbCredentials); StatusLog.AddStatus("Upload content details: " + dataSource.ToString(), -10); StatusLog.AddStatus("Success! Uploaded datasource " + Path.GetFileName(localFilePath)); } catch (Exception exPublishFinalize) { this.StatusLog.AddError("Unexpected error finalizing publish of file " + localFilePath + ", " + exPublishFinalize.Message); throw exPublishFinalize;; } return(true); //Success }
/// <summary> /// After a file has been uploaded in chunks, we need to make a call to COMMIT the file to server as a published Workbook /// </summary> /// <param name="uploadSessionId"></param> /// <param name="publishedContentName"></param> private SiteWorkbook FinalizePublish( string uploadSessionId, string publishedContentName, string publishedContentType, string projectId, CredentialManager.Credential dbCredentials, WorkbookPublishSettings publishSettings) { if (projectId == null) { projectId = ""; } //See definition: http://onlinehelp.tableau.com/current/api/rest_api/en-us/help.htm#REST/rest_api_ref.htm#Publish_Workbook%3FTocPath%3DAPI%2520Reference%7C_____29 var sb = new StringBuilder(); //Build the XML part of the MIME message we will post up to server var xmlWriter = XmlWriter.Create(sb, XmlHelper.XmlSettingsForWebRequests); xmlWriter.WriteStartElement("tsRequest"); xmlWriter.WriteStartElement("workbook"); xmlWriter.WriteAttributeString("name", publishedContentName); xmlWriter.WriteAttributeString("showTabs", XmlHelper.BoolToXmlText(publishSettings.ShowTabs)); //If we have an associated database credential, write it out if (dbCredentials != null) { CredentialXmlHelper.WriteCredential( xmlWriter, dbCredentials); } xmlWriter.WriteStartElement("project"); //<project> xmlWriter.WriteAttributeString("id", projectId); xmlWriter.WriteEndElement(); //</project> xmlWriter.WriteEndElement(); // </workbook> xmlWriter.WriteEndElement(); // </tsRequest> xmlWriter.Dispose(); var xmlText = sb.ToString(); //Get the XML text out //Generate the MIME message and pack the XML into it var mimeGenerator = new MimeWriterXml(xmlText); //Create a web request to POST the MIME message to server to finalize the publish var urlFinalizeUpload = Urls.Url_FinalizeWorkbookPublish(Login, uploadSessionId, publishedContentType); //NOTE: The publish finalization step can take several minutes, because server needs to unpack the uploaded ZIP and file it away. // For this reason, we pass in a long timeout var response = CreateAndSendMimeLoggedInRequest(urlFinalizeUpload, HttpMethod.Post, mimeGenerator); using (response) { var xmlDoc = GetHttpResponseAsXml(response); var xDoc = xmlDoc.ToXDocument(); var workbookXml = xDoc.Root.Descendants(XName.Get("workbook", XmlNamespace)).FirstOrDefault(); try { return(new SiteWorkbook(workbookXml.ToXmlNode(), XmlNamespace)); } catch (Exception parseXml) { Login.Logger.Error("Workbook upload, error parsing XML response " + parseXml.Message + "\r\n" + workbookXml.ToXmlNode().InnerXml); return(null); } } }
/// <summary> /// Writes out the credential element. Used in Workbook and Data Source publication /// </summary> /// <param name="xmlWriter"></param> /// <param name="credential"></param> public static void WriteCredential(XmlWriter xmlWriter, CredentialManager.Credential credential) { WriteCredential(xmlWriter, credential.Name, credential.Password, credential.IsEmbedded); }