Last active
October 13, 2020 12:31
-
-
Save saionaro/7ee0e2c02749e2729dc429c9e9bfa7f3 to your computer and use it in GitHub Desktop.
A direct file uploading, react native edition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//... | |
// some interfaces imports skipped | |
//... | |
const createDirectUploadMutation = ` | |
mutation createDirectUploadMutation( | |
$filename: String! | |
$byteSize: Int! | |
$contentType: String! | |
) { | |
createDirectUpload( | |
input: { | |
filename: $filename | |
byteSize: $byteSize | |
contentType: $contentType | |
} | |
) { | |
directUpload { | |
blobId | |
headers | |
signedBlobId | |
url | |
} | |
} | |
} | |
`; | |
//... | |
// skip some interface declarations | |
// two most important can be found at the end of file | |
//... | |
export class Uploader implements IUploader { | |
public constructor( | |
private client: IApiClient, | |
private file: IFile, | |
) {} | |
public async upload(): Promise<IUploadFileResult> { | |
const response: ICreateDirectUploadResult = await this.client.query( // lets say - it just the fetch with some tweaks | |
createDirectUploadMutation, | |
this.file, | |
); | |
//... | |
// some boring validation logic skipped | |
//... | |
const { directUpload } = response.createDirectUpload; | |
const blob = await this.toBlob(this.file.uri); | |
await this.performUpload(blob, directUpload); | |
return { | |
signedId: directUpload.signedBlobId, | |
id: directUpload.blobId, | |
}; | |
} | |
private async toBlob(uri: string): Promise<Blob> { | |
return await new Promise((resolve, reject) => { | |
const xhr = new XMLHttpRequest(); | |
xhr.onload = () => resolve(xhr.response); | |
xhr.onerror = () => reject(new UploadFileError("notFound")); | |
xhr.responseType = "blob"; | |
xhr.open("GET", uri, true); | |
xhr.send(null); | |
}); | |
} | |
private performUpload( | |
blob: Blob, | |
directUpload: IDirectUpload, | |
): Promise<void> { | |
return new Promise((resolve, reject) => { | |
const req = new XMLHttpRequest(); | |
const headers = JSON.parse(directUpload.headers); | |
req.open("PUT", directUpload.url, true); | |
for (let header in headers) { | |
req.setRequestHeader(header, headers[header]); | |
} | |
req.onload = () => resolve(); | |
req.onerror = () => reject(Err(new UploadFileError("transportError"))); | |
req.send(blob); | |
}); | |
} | |
} | |
interface IFile { | |
filename: string; | |
byteSize: number; | |
contentType: string; | |
uri: string; | |
} | |
interface IDirectUpload { | |
blobId: string; | |
headers: string; | |
signedBlobId: string; | |
url: string; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Uploader } from "src/Uploader"; | |
import { ApiClient } from "src/ApiClient"; | |
const file = { | |
filename: "dev.to", // file name | |
contentType: "image/jpeg", // file content type | |
uri: "path/to/local/file", // local file path at your device | |
byteSize: 2019, // size in bytes | |
}; | |
const apiClient = new ApiClient(...); | |
const uploaderInstance = new Uploader(apiClient, file); | |
const responce = await uploaderInstance.upload(); | |
const { signedId } = responce; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment