Forum Discussion
Import PBIX via Postman
- 8 years ago
I was able to get Fiddler to work and used that to fix my Java version. I've included the script below (thanks to Zhang)
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.HttpClientBuilder; public class ImportPBIXUtil { public static void main( String[] args ) { try { Import(); } catch ( UnsupportedOperationException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( IOException e ) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void Import() throws UnsupportedOperationException, IOException { String bearer = "Bearer {token}"; String fileName = "myReport.pbix"; String filePath = "C:\\Users\\JohnDoe\\Documents\\PowerBI\\" + fileName; String groupId = "{group_id}"; HttpClient request = HttpClientBuilder.create().build(); HttpPost post = new HttpPost( "https://api.powerbi.com/v1.0/myorg/groups/" + groupId + "/imports?datasetDisplayName=MyNewReport" ); long time = (new Date()).getTime(); String boundary = "---------------------------" + time; post.setHeader( "ContentType", "multipart/form-data; boundary=" + boundary ); post.setHeader( "Authorization", bearer ); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setBoundary( boundary ); builder.addBinaryBody( "filename", new File( filePath ), ContentType.APPLICATION_OCTET_STREAM, fileName ); HttpEntity multipart = builder.build(); post.setEntity( multipart ); HttpResponse response = null; System.out.println( "Request: " ); for (Header header : post.getAllHeaders()) { System.out.println( header.getName() + " : " + header.getValue() ); } System.out.println( post.getEntity().getContentLength() ); /*/ BufferedReader reqd = new BufferedReader( new InputStreamReader( post.getEntity().getContent() ) ); StringBuffer bbody = new StringBuffer(); String l = ""; while ( (l = reqd.readLine()) != null ) { bbody.append( l ); } System.out.println( bbody.toString() ); /*/ System.out.println( "Response: " ); try { response = request.execute( post ); } catch ( ClientProtocolException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( IOException e ) { // TODO Auto-generated catch block e.printStackTrace(); } BufferedReader rd = new BufferedReader( new InputStreamReader( response.getEntity().getContent() ) ); StringBuffer result = new StringBuffer(); String line = ""; while ( (line = rd.readLine()) != null ) { result.append( line ); } System.out.println( response.getStatusLine().getStatusCode() ); System.out.println( result.toString() ); return; } }
dgdragon wrote:
I am trying to import a PBIX file using postman, but all I get is a 400 with empty message. I have tried many ways, form-data, json, binary, so I must be missing something. Anyone able to do this in postman?
I love Postman, however Postman seems not supporting the Content-Type: application / octet, see this link.
I usually use below code to import pbix file, just for your reference.
using System;
using System.Net;
//Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.21.301221612
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.IO;
namespace ConsoleApplication39
{
class Program
{
//Step 1 - Replace {client id} with your client app ID.
//To learn how to get a client app ID, see Register a client app (https://msdn.microsoft.com/en-US/library/dn877542.aspx#clientID)
private static string clientID = "49dxxxxxxxxx770d1a4";
//RedirectUri you used when you registered your app.
//For a client app, a redirect uri gives AAD more details on the specific application that it will authenticate.
private static string redirectUri = "https://login.live.com/oauth20_desktop.srf";
//Resource Uri for Power BI API
private static string resourceUri = "https://analysis.windows.net/powerbi/api";
//OAuth2 authority Uri
private static string authority = "https://login.windows.net/common/oauth2/authorize";
private static AuthenticationContext authContext = null;
private static string token = String.Empty;
//Uri for Power BI datasets
private static string datasetsUri = "https://api.powerbi.com/v1.0/myorg";
// private static string datasetsBetaUri = "https://api.powerbi.com/beta/myorg";
//Example dataset name and group name
private static string groupId = "dc581xxxxxxxxxxb6c15";
static void Main(string[] args)
{
//Import sample
string pbixPath = @"C:\test\test.pbix";
string datasetDisplayName = "IamDataSetName";
string importResponse = Import(string.Format("{0}/groups/{1}/imports?datasetDisplayName={2}", datasetsUri, groupId, datasetDisplayName), pbixPath);
Console.WriteLine(importResponse);
}
public static string Import(string url, string fileName)
{
string responseStatusCode = string.Empty;
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.KeepAlive = true;
request.Headers.Add("Authorization", String.Format("Bearer {0}", AccessToken()));
using (Stream rs = request.GetRequestStream())
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; filename=\"{0}\"\r\nContent-Type: application / octet - stream\r\n\r\n";
string header = string.Format(headerTemplate, fileName);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
}
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
}
using (HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse)
{
responseStatusCode = response.StatusCode.ToString();
}
return responseStatusCode;
}
static string AccessToken()
{
if (token == String.Empty)
{
//Get Azure access token
// Create an instance of TokenCache to cache the access token
TokenCache TC = new TokenCache();
// Create an instance of AuthenticationContext to acquire an Azure access token
authContext = new AuthenticationContext(authority, TC);
// Call AcquireToken to get an Azure token from Azure Active Directory token issuance endpoint
token = authContext.AcquireToken(resourceUri, clientID, new Uri(redirectUri), PromptBehavior.RefreshSession).AccessToken;
}
else
{
// Get the token in the cache
token = authContext.AcquireTokenSilent(resourceUri, clientID).AccessToken;
}
return token;
}
}
}
I tried using the code (just hard coded the bearer token) but it just exits with "Unhandled Exception: System.Net.WebException: The remote server returned an error: (400) Bad Request."
Additionally I've tried Fiddler and followed this tutorial https://powerbi.microsoft.com/en-us/blog/upload-a-local-pbix-file-using-the-import-api/ with the same result.
I also constructed a java version using MultipartEntityBuilder, which also has the same result.
So far I've recieved only 400's with a body of {"Message":""}, an HTML page that says the request contained invalid headers (does not say what headers), or {"error":{"code":"PowerBIModelNotFoundException","pbi.error":{"code":"PowerBIModelNotFoundException","parameters":{},"details":[]}}}
UPDATE:
I did manage to get a 202 and an ID using Fiddler, but it doesnt actually do anything. It does not show up in PowerBI or using the get /imports route.