diff --git a/package.json b/package.json
index c9af63d94d57dc5cccc655bd6a3471f5968131e8..82e8725659b312fed1f981c073df3510d6905ba1 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
     "bluebird": "^3.4.7",
     "discord.js": "^11.0.0",
     "js-yaml": "^3.8.1",
+    "mime": "^1.3.4",
     "npmlog": "^4.0.2",
     "tslint": "^4.4.2",
     "typescript": "^2.1.6"
diff --git a/src/util.ts b/src/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1cb4b3695cb908ee2779bb581d0d5d7ce0f34d03
--- /dev/null
+++ b/src/util.ts
@@ -0,0 +1,73 @@
+import * as http from "http";
+import * as https from "https";
+import { Bridge, Intent } from "matrix-appservice-bridge";
+import { Buffer } from "buffer";
+import * as log from "npmlog";
+import * as mime from "mime";
+
+export class Util {
+  /**
+   * uploadContentFromUrl - Upload content from a given URL to the homeserver
+   * and return a MXC URL.
+   */
+  public static uploadContentFromUrl(bridge: Bridge, url: string, id: string | Intent, name: string): Promise<any> {
+    let contenttype;
+    let size;
+    id = id || null;
+    name = name || null;
+    return new Promise((resolve, reject) => {
+      let ht;
+      if (url.startsWith("https")) {
+        ht = https;
+      } else {
+        ht = http;
+      }
+      const req = ht.get( url, (res) => {
+        let buffer = Buffer.alloc(0);
+
+        if (res.headers.hasOwnProperty("content-type")) {
+          contenttype = res.headers["content-type"];
+        } else {
+          log.verbose("UploadContent", "No content-type given by server, guessing based on file name.");
+          contenttype = mime.lookup(url);
+        }
+
+        if (name === null) {
+          let names = url.split("/");
+          name = names[names.length - 1];
+        }
+
+        res.on("data", (d) => {
+          buffer = Buffer.concat([buffer, d]);
+        });
+
+        res.on("end", () => {
+          resolve(buffer);
+        });
+      });
+      req.on("error", (err) => {
+        reject(`Failed to download. ${err.code}`);
+      });
+    }).then((buffer: Buffer) => {
+      size = buffer.length;
+      if (id === null || typeof id === "string") {
+        id = bridge.getIntent(id);
+      }
+      return id.getClient().uploadContent(buffer, {
+        name,
+        type: contenttype,
+        onlyContentUri: true,
+        rawResponse: false,
+      });
+    }).then((contentUri) => {
+      log.verbose("UploadContent", "Media uploaded to %s", contentUri);
+      return {
+        mxc_url: contentUri,
+        size,
+      };
+    }).catch((reason) => {
+      log.error("UploadContent", "Failed to upload content:\n%s", reason);
+      throw reason;
+    });
+  }
+}