I'm new to angular and I'm trying to create a download link upon button click that downloads doc file. The file gets downloaded successfully but the content inside is something else which is '[object Object]'. The file path is in my webroot and I'm accessing the file like this:
[Route("api/[Controller]")]
[ApiController]
public class DownloadController : Controller
{
private readonly IWebHostEnvironment _env;
public DownloadController(IWebHostEnvironment env)
{
_env = env;
}
[HttpGet]
public async Task<IActionResult> Download()
{
string filePath = Path.Combine(_env.WebRootPath, "Image\\CV.doc");
using MemoryStream memorystream = new MemoryStream();
using (var stream = new FileStream(filePath, FileMode.Open))
{
await stream.CopyToAsync(memorystream);
}
memorystream.Position = 0;
return File(memorystream, "application/msword", "CV.doc");
}
}
my Shared service.ts. I've changed the observe to 'body' as well.
import { Injectable } from '#angular/core';
import { HttpClient, HttpResponse } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class SharedService {
cvFilePathURL = "https://localhost:44346/api/Download";
constructor(private http: HttpClient) { }
getCV(): Observable<any> {
return this.http.get(this.cvFilePathURL, {
observe: 'response',
responseType: 'text'
});
}
}
and this is my componenet.ts
import { Component } from '#angular/core';
import { SharedService } from 'src/app/shared.service';
#Component({
selector: 'app-nav-menu',
templateUrl: './nav-menu.component.html',
styleUrls: ['./nav-menu.component.css']
})
export class NavMenuComponent {
constructor(private service: SharedService) { }
isExpanded = false;
collapse() {
this.isExpanded = false;
}
toggle() {
this.isExpanded = !this.isExpanded;
}
public Download(): void {
this.service.getCV().subscribe((data) => {
var newBlob = new Blob([data], { type: "application/msword" });
//For Internet Explorer
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
return window.navigator.msSaveOrOpenBlob(newBlob);
}
//For other browsers:
//Create a link pointing to the ObjectURL containing the blob.
const mainData = window.URL.createObjectURL(newBlob);
var link = document.createElement('a');
link.href = mainData;
link.download = "CV.doc";
link.click();;
});
}
}
target framework - asp.net core 3.1
Angular Cli - 11.0.6
Update:
So I've managed to download file which has actual contents other than [objects Objects]. However, The file is filled with special characters and is 206 pages long. Original document is only 2 pages long.
I think there are some changes you might have to do inside your code or you can check my code what I am going to provide below.
YOU CONTROLLER
[HttpPost]
[Route("get-download-file")]
public HttpResponseMessage GetDownloadFile(dynamic data)
{
// var localFilePath = HttpContext.Current.Server.MapPath("~/Documents/" + (string)data.fileName);
var localFilePath = HttpContext.Current.Server.MapPath((string)data.mappingPath);
string contentType = MimeMapping.GetMimeMapping(Path.GetExtension(localFilePath));
HttpResponseMessage response = null;
try
{
if (!File.Exists(localFilePath))
{
//if file not found than return response as resource not present
response = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
//if file present than read file
var fStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
//compose response and include file as content in it
response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(fStream)
};
//set content header of reponse as file attached in reponse
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileName(fStream.Name)
};
//set the content header content type as application/octet-stream as it returning file as reponse
response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
}
}
catch (Exception ex)
{
return response;
}
return response;
}
In your Service(Angular) add that httpPostMethod:
public httpPostFile(url: string, body: any): Observable<Blob> {
return this.httpClient.post<Blob>(this.baseUri + url, body, { responseType: 'blob' as 'json' })
.pipe(
catchError(this.handleClientError)
);
}
Finally, you have to call that method from angular. Using code below->
let tempBlob: any;
let contentFileType= 'txt'; //you can make that file type dynamic using some addional code.
const data = {
fileName: this.fileName,
mappingPath: '~/Documents/' + this.fileName
};
this.apiService.httpPostFile('download/get-download-file/', data)
.subscribe(fileData => {
tempBlob = new Blob([fileData], { type: contentFileType });
},
(error) => {
}, () => {
const blob: Blob = new Blob(tempBlob, { type: contentFileType });
const fileName: string = this.filedlName;
const objectUrl: string = URL.createObjectURL(blob);
const a: HTMLAnchorElement = document.createElement('a') as HTMLAnchorElement;
a.href = objectUrl;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(objectUrl);
});
Note: There can be more efficient way to download a file in angular and ASP MVC Web API. But this way it worked for me. you can try it. If you find any difficulties than feel free to ask. Thank you.
Related
I let my users upload their profile image, which shows as a 150x150 pixels circle, I want the image to be resized/compress when he selects it to upload to Firebase. Here is my JavaScript to select and upload the image:
<label for="upload-picture" class="upload-picture button-small">Upload Picture</label>
<input id="upload-picture" type="file" style="display: none" (change)="uploadPicture($event)" accept=".jpeg,.jpg,.png,.svg">
import { Component, OnInit } from '#angular/core';
import { AngularFirestoreDocument } from '#angular/fire/firestore';
import { FbUser } from 'src/app/common/fb-user';
import { AuthService } from 'src/app/services/auth.service';
#Component({
selector: 'app-profile-info',
templateUrl: './profile-info.component.html',
styleUrls: ['./profile-info.component.scss']
})
export class ProfileInfoComponent implements OnInit {
constructor(
public _auth: AuthService,
) { }
ngOnInit(): void {
}
currentImageUrl: string = "";
async uploadPicture(e: any) {
const file = e.target.files[0]
//Here i want to reduce image size
//(image shows as a 150x150 in the DOM so i dont need it to be bigger than that since firebase has a 5GB limit of free storage)
const filePath = this._auth.userData.uid
const task = await this.uploadImage(filePath, file)
if (task) {
this.currentImageUrl = await this._auth._afstg.ref(task).getDownloadURL().toPromise();
const userRef: AngularFirestoreDocument<any> = this._auth._afs.doc(`users/${filePath}`);
const userData: FbUser = {
uid: filePath,
email: this._auth.userData.email,
displayName: this._auth.userData.displayName,
photoURL: this.currentImageUrl,
emailVerified: this._auth.userData.emailVerified
}
userRef.set(userData, {
merge: true
})
alert("Image Uploaded Successfully")
window.location.reload()
} else {
alert("Error when uploading image, try again")
}
}
async uploadImage(uid: string, file: any): Promise<string> {
const fileRef = this._auth._afstg.ref(uid).child("profile-picture");
// Upload file in reference
if (!!file) {
const result = await fileRef.put(file);
return result.ref.fullPath;
}
return ""
}
}
I've tried many approaches, but none seems to be working, anyone got any idea or have done this before?
You can use this, to convert base64 to file blob.
const split = base64Image.split(',');
const type = split[0].replace('data:', '').replace(';base64', '');
const byteString = atob(split[1]);
const arrayBuffer = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i += 1) {
ia[i] = byteString.charCodeAt(i);
}
const fileBlob = new Blob([arrayBuffer], {type}); // upload this to firebase.
I can find a lot of resources online on how to track upload progress to S3 using aws-sdk V2, listening to the event like:
.on('httpUploadProgress', event => {}
But since I updated the aws-sdk to V3, there are no listeners anymore. I believe I have to use the middleware function now, but I've tried a few things and it didn't work. I've also went deep into the API reference docs and the github repository without success.
My current code is like this:
import { S3Client, PutObjectCommand } from '#aws-sdk/client-s3';
export const UploadToS3 = (credentials, fileData) => {
const s3 = new S3Client({
region: credentials.region,
credentials: {
accessKeyId: credentials.access_key,
secretAccessKey: credentials.secret_key,
sessionToken: credentials.session_token,
}
});
return new Promise((resolve) => {
s3.send(new PutObjectCommand({
Bucket: credentials.bucket,
Key: credentials.file,
Body: fileData,
}));
});
};
Any help would be appreciated
I had exactly the same problem (switched from aws-sdk v2 to v3) and found out that it is because the library uses the Fetch API for all HTTP Requests and Fetch does not (yet) support tracking upload progress
To solve that problem I exchanged Fetch by good old XMLHttpRequest at least for PUT requests, which you can accomplish by providing a custom requestHandler when initializing the S3Client.
import { S3Client } from '#aws-sdk/client-s3';
const myHttpHandler = new MyHttpHandler();
myHttpHandler.onProgress$.subscribe(progress => {
const percentComplete = progress.progressEvent.loaded / progress.progressEvent.total * 100;
console.log('upload progress', percentComplete);
});
const myClient = new S3Client({
endpoint: this.configService.s3Api,
region: 'eu',
credentials: { ... },
requestHandler: myHttpHandler
});
The custom request handler simply extends the FetchHttpHandler from #aws-sdk/fetch-http-handler. If the method is PUT and there is a body (so we want to upload something), it uses a custom XHR handler - otherwise it just uses the Fetch handler from it's super class.
And in the XHR handler you can bind something to the progress event of the XHR handler - in my case I emit a rxjs Subject which I can consume outside the custom handler.
import { FetchHttpHandler, FetchHttpHandlerOptions } from '#aws-sdk/fetch-http-handler';
import { HeaderBag, HttpHandlerOptions } from '#aws-sdk/types';
import { buildQueryString } from '#aws-sdk/querystring-builder';
import { HttpResponse, HttpRequest } from '#aws-sdk/protocol-http';
import { Subject } from 'rxjs';
class MyHttpHandler extends FetchHttpHandler {
private myRequestTimeout;
onProgress$: Subject<{ path: string, progressEvent: ProgressEvent }> = new Subject();
constructor({ requestTimeout }: FetchHttpHandlerOptions = {}) {
super({ requestTimeout });
this.myRequestTimeout = requestTimeout;
}
handle(request: HttpRequest, { abortSignal }: HttpHandlerOptions = {}): Promise<{ response: HttpResponse }> {
// we let XHR only handle PUT requests with body (as we want to have progress events here), the rest by fetch
if (request.method === 'PUT' && request.body) {
return this.handleByXhr(request, { abortSignal });
}
return super.handle(request, { abortSignal });
}
/**
* handles a request by XHR instead of fetch
* this is a copy the `handle` method of the `FetchHttpHandler` class of #aws-sdk/fetch-http-handler
* replacing the `Fetch`part with XHR
*/
private handleByXhr(request: HttpRequest, { abortSignal }: HttpHandlerOptions = {}): Promise<{ response: HttpResponse}> {
const requestTimeoutInMs = this.myRequestTimeout;
// if the request was already aborted, prevent doing extra work
if (abortSignal?.aborted) {
const abortError = new Error('Request aborted');
abortError.name = 'AbortError';
return Promise.reject(abortError);
}
let path = request.path;
if (request.query) {
const queryString = buildQueryString(request.query);
if (queryString) {
path += `?${queryString}`;
}
}
const { port, method } = request;
const url = `${request.protocol}//${request.hostname}${port ? `:${port}` : ''}${path}`;
// Request constructor doesn't allow GET/HEAD request with body
// ref: https://github.com/whatwg/fetch/issues/551
const body = method === 'GET' || method === 'HEAD' ? undefined : request.body;
const requestOptions: RequestInit = {
body,
headers: new Headers(request.headers),
method,
};
const myXHR = new XMLHttpRequest();
const xhrPromise = new Promise<{headers: string[], body: Blob, status: number}>((resolve, reject) => {
try {
myXHR.responseType = 'blob';
// bind the events
myXHR.onload = progressEvent => {
resolve({
body: myXHR.response,
headers: myXHR.getAllResponseHeaders().split('\n'),
status: myXHR.status
});
};
myXHR.onerror = progressEvent => reject(new Error(myXHR.responseText));
myXHR.onabort = progressEvent => {
const abortError = new Error('Request aborted');
abortError.name = 'AbortError';
reject(abortError);
};
// progress event musst be bound to the `upload` property
if (myXHR.upload) {
myXHR.upload.onprogress = progressEvent => this.onProgress$.next({ path, progressEvent });
}
myXHR.open(requestOptions.method, url);
// append headers
if (requestOptions.headers) {
(requestOptions.headers as Headers).forEach((headerVal, headerKey, headers) => {
if (['host', 'content-length'].indexOf(headerKey.toLowerCase()) >= 0) {
// avoid "refused to set unsafe header" error message
return;
}
myXHR.setRequestHeader(headerKey, headerVal);
});
}
myXHR.send(requestOptions.body);
} catch (e) {
console.error('S3 XHRHandler error', e);
reject(e);
}
});
const raceOfPromises = [
xhrPromise.then((response) => {
const fetchHeaders = response.headers;
const transformedHeaders: HeaderBag = {};
fetchHeaders.forEach(header => {
const name = header.substr(0, header.indexOf(':') + 1);
const val = header.substr(header.indexOf(':') + 1);
if (name && val) {
transformedHeaders[name] = val;
}
});
const hasReadableStream = response.body !== undefined;
// Return the response with buffered body
if (!hasReadableStream) {
return response.body.text().then(body => ({
response: new HttpResponse({
headers: transformedHeaders,
statusCode: response.status,
body,
}),
}));
}
// Return the response with streaming body
return {
response: new HttpResponse({
headers: transformedHeaders,
statusCode: response.status,
body: response.body,
}),
};
}),
this.requestTimeoutFn(requestTimeoutInMs),
];
if (abortSignal) {
raceOfPromises.push(
new Promise<never>((resolve, reject) => {
abortSignal.onabort = () => {
myXHR.abort();
};
})
);
}
return Promise.race(raceOfPromises);
}
private requestTimeoutFn(timeoutInMs = 0): Promise<never> {
return new Promise((resolve, reject) => {
if (timeoutInMs) {
setTimeout(() => {
const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
timeoutError.name = 'TimeoutError';
reject(timeoutError);
}, timeoutInMs);
}
});
}
}
Looking through the github issues I've just found that #aws-sdk/client-s3 don't support upload progress tracking, since it uses fetchHttpHandler under the covers. The recommended way is to use #aws-sdk/lib-storage which I have not tried yet, but looks promising!
I have also faced the same issue that is i have to upgrade aws-sdk from v2 to v3 but file upload progress feature is missing in v3.The reason for that is in JS SDK v2 for S3 file upload they uses XHR for browser network requests, which has a good interface for progress tracking.
Whereas JS SDK v3 uses fetch for the same, which offers some other advantages but one downside is that it does not seem to support upload progress yet, and progress on that feature is extremely slow.
But now JS SDK v3 has a new package called #aws-sdk/xhr-http-handler which can be used in place of #aws-sdk/fetch-http-handler in order to get the fine grained file upload progress as we are getting in v2.
You can find out the code for that on the link https://github.com/aws/aws-sdk-js-v3/tree/main/packages/xhr-http-handler
import { S3Client } from '#aws-sdk/client-s3';
import { XhrHttpHandler } from '#aws-sdk/xhr-http-handler';
import { Upload } from '#aws-sdk/lib-storage';
const s3Client = new S3Client({
requestHandler: new XhrHttpHandler({}),
});
const upload = new Upload({
client:s3Client,
params: {
bucket,
key,
},
});
upload.on("httpUploadProgress", (progress) => {
console.log(
progress.loaded, // Bytes uploaded so far.
progress.total // Total bytes. Divide these two for progress percentage.
);
});
await upload.done();
I am using a POST method to get a byte array of an excel file
c# server side implementation:
downloadExcel() {
....
FileResultDto fileResultDto = new FileResultDto
{
Data = ExcelHelper.CreateExcelFile(excelFile) //Data contains the byte array
};
return new JsonHttpResponseMessage(JsonConvert.SerializeObject(fileResultDto));
}
CreateExcelFile():
public byte[] CreateExcelFile(ExcelFile excelFile)
{
try
{
#region Validation
if (excelFile == null)
{
throw new ArgumentNullException(nameof(excelFile));
}
#endregion
byte[] bytes;
using (ExcelPackage excelPackage = new ExcelPackage())
{
for (int i = 1; i <= excelFile.Worksheets.Count; i++)
{
Worksheet worksheet = excelFile.Worksheets[i - 1];
excelPackage.Workbook.Worksheets.Add(worksheet.Name);
ExcelWorksheet currentExcelWorksheet = excelPackage.Workbook.Worksheets[i];
if (excelFile.HasLogoTemplate)
{
byte[] imageBytes = Convert.FromBase64String(LogoBase64);
Image image;
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
image = Image.FromStream(ms, true);
}
ExcelPicture picture = currentExcelWorksheet.Drawings.AddPicture("Logo", image);
picture.SetPosition(0, 4, 0, 10);
currentExcelWorksheet.Row(1).Height = 50;
}
SetColumnsWidths(currentExcelWorksheet, worksheet);
WriteHeaderRow(currentExcelWorksheet, worksheet.HeaderRow);
WriteCells(currentExcelWorksheet, worksheet.Cells);
}
#region Set Excel Stream
bytes = excelPackage.GetAsByteArray();
#endregion
}
return bytes;
}
catch (Exception exception)
{
throw new Exception("There was an error on excel export. Exception: ", exception);
}
}
front end implementation:
public downloadExcel(): void {
this.myRepository.downloadExcel(this.postData).then(result => {
var byteArray = new Uint8Array(result.data.data);
var a = window.document.createElement('a');
a.href = window.URL.createObjectURL(new Blob([byteArray], { type: "application/octet-stream" }));
a.download = "test.xlsx";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}, error => {
console.log(error);
});
}
Apparently the created blob file it seems to be corrupted. Any suggestions where the problem can be?
Finally the problem solved using 'arraybuffer' as the response type of the http request.
let requestConfiguration: ng.IRequestConfig = {
cache: ...,
data: ...,
headers: ...,
method: ...,
url: ...,
responseType: 'arraybuffer'
};
let promise: ng.IPromise<any> = this.$http(requestConfiguration);
The same is done in Angular. This might be help you
downloadExcel(){
this.downloadAttachment(filename).subscribe(res => {
let Res=res;
const downloadedFile = new Blob([Res], { type: Res.type });
const a = document.createElement('a');
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
a.download = attachment.filename;
a.href = URL.createObjectURL(downloadedFile);
a.target = '_blank';
a.click();
document.body.removeChild(a);
},
err=>{
throw err;
})
}
downloadAttachment(filename){
this.httpOptions = {
reportProgress: true,
responseType: "blob"
};
return this.http.get(API_URL, this.httpOptions).pipe(
map(response => response),
catchError(this.handleError<any>(isShowError)),
finalize(() => {
})
);
}
C# Code
var res=DownloadAttachment(filename);
if (res == null)
return Content("filename not present");
return File(res, Utility.GetContentType(filename), filename);
I have one demo-file.csv file and it is in the assets/csv folder, so how can I download it from mobile,
here is my HTML & COMPONENT code.
HTML CODE
<button ion-button type="button" block (click)="downloadFile('assets/csv/demo-file.csv', 'demo-file.csv')">Download Demo File</button>
COMPONENT CODE
public downloadFile(link: any, fileName: any) {
if (link) {
let path = null;
this.showWaitingLoading();
if (this.platform.is('ios')) {
path = this.file.documentsDirectory;
} else {
path = this.file.dataDirectory;
}
const transfer = this.transfer.create();
transfer.download(link, path + fileName).then(entry => {
this.dismissWaitingLoading();
this.openFile(entry.toURL());
}).catch(() => {
this.dismissWaitingLoading();
this.showToastMsg('error', "Something went wrong");
});
}
}
/* ================= OPNE FILE FUNCTION ===========*/
public openFile(path: any) {
this.fileOpener.open(path, 'application/*')
.then(() => console.log('File is opened'))
.catch((e: any) => console.log('Error openening file', e));
}
I'm not able to download the file, is there any thing missing in my PATH?
Try to read it using Http get and write it as a Blob, Sample code as follows,
export class csvPage {
csvData: any[] = [];
headerRow: any[] = [];
constructor(public navCtrl: NavController,
public navParams: NavParams,
private http: Http) {
this.readCsvData();
}
private readCsvData() {
this.http.get('assets/dummyData.csv')
.subscribe(
data => this.extractData(data),
err => this.handleError(err)
);
}
private extractData(res) {
let csvData = res['_body'] || '';
let parsedData = papa.parse(csvData).data;
this.headerRow = parsedData[0];
parsedData.splice(0, 1);
this.csvData = parsedData;
}
downloadCSV() {
let csv = papa.unparse({
fields: this.headerRow,
data: this.csvData
});
// Dummy implementation for Desktop download purpose
var blob = new Blob([csv]);
var a = window.document.createElement("a");
a.href = window.URL.createObjectURL(blob);
a.download = "newdata.csv";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
private handleError(err) {
console.log('something went wrong: ', err);
}
}
Html Code
<button ion-button type="button" block (click)="downloadFile('demo-file.csv')">Download Demo File</button>
Component Code
declare var cordova: any; // declare Top Section of component
public downloadFile(link: any) {
if (link) {
let path = null;
this.showWaitingLoading();
if (this.platform.is('ios')) {
path = cordova.file.documentsDirectory;
} else {
path = cordova.file.dataDirectory;
}
const transfer = this.transfer.create();
const imageLocation = `${cordova.file.applicationDirectory}www/assets/csv/${link}`;
transfer.download(imageLocation, path + link).then(entry => {
this.dismissWaitingLoading();
this.openFile(entry.toURL());
}).catch(() => {
this.dismissWaitingLoading();
this.showToastMsg('error', "Something went wrong");
})
}
/* ================= OPNE FILE FUNCTION ===========*/
public openFile(path: any) {
this.fileOpener.open(path, 'application/*')
.then(() => console.log('File is opened'))
.catch((e: any) => console.log('Error openening file', e));
}
Please try this one
You can use a library... Also, the HttpClient can read data as Blob for you.
npm i file-saver
// my.component.ts
import * as fileSaver from 'file-saver';
export class MyComponent {
constructor(private http: HttpClient){}
downloadFile(path: string) {
this.startLoading();
this.http.get(`${MY_APP_URL}/${path}`, { responseType: 'blob' })
.pipe(tap(blob: Blob => fileSaver.saveAs(blob, 'your_csv_file_name.csv')))
.subscribe(() => this.stopLoading(), err => this.handleErr(err));
}
}
Hope this helps a little :-)
Currently my code looks like this:
module Nexus {
export class Scraper {
private summonerName: string;
private apiKey: string = '';
private summonerStatsUrl = '';
constructor(name: string) {
this.summonerName = name;
}
getSeasonRank(): string {
return 'aa';
}
getRankedStats(): string {
return 'aa';
}
getSummonerStats(callback: Function) {
var summonerStats = request(this.summonerStatsUrl + this.apiKey, function (error, body, response) {
callback(response);
});
}
}
}
And app.ts:
///<reference path="./Nexus.ts"/>
var colors = require('colors'),
request = require('request'),
fs = require('fs'),
readline = require('readline'),
rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Insert summoner name: \r\n >> ', function (answer) {
var scraper = new Nexus.Scraper(answer);
scraper.getSummonerStats(function (result) {
console.log(result);
});
});
When I reach the new Nexus.Scraper(), I'm getting this error:
Nexus is not defined
While it should be since I'm including it? The module is named Nexus and I'm exporting the Scraper class. (The file is called Nexus.ts.)
Make sure your module looks as follows:
module Nexus {
export class Scraper {
private summonerName: string;
private apiKey: string = '';
private summonerStatsUrl = '';
constructor(name: string) {
this.summonerName = name;
}
getSeasonRank(): string {
return 'aa';
}
getRankedStats(): string {
return 'aa';
}
getSummonerStats(callback: Function) {
var summonerStats = request(this.summonerStatsUrl + this.apiKey, function (error, body, response) {
callback(response);
});
}
}
}
export = Nexus;
Then, rather than using /// <reference /> do this:
import Nexus = require('Nexus');
You also need to export the module
export module Nexus {
...
}
then in your app.ts you can call it like:
import Nexus = require('./Nexus.ts');